Android:同步线程和处理程序

时间:2013-04-15 14:40:19

标签: java android synchronization handler seekbar

我的应用程序遇到了一些问题。我对Android开发很新,所以我希望这是一个容易犯的错误。 所以我正在尝试编写一个通过Wifi(第一个线程)获取一些原始数据的应用程序,进行一些计算(第二个线程),从计算出的数据(第三个线程)中创建一个位图并更新显示(处理程序)。 一些参数由SeekBars调整。一切正常。但有时当我更改seekBarValues时,图片不再更新。线程和处理程序仍在运行,所以我不会收到错误。

这里有一些代码:

MainActivity:

public class MainActivity extends Activity implements OnClickListener {
    private Handler outputHandler = new Handler();
    private SeekBar  seekBarBrightness,
    seekBarContrast,
    seekBarGamma;

    public static volatile double gamma = 1;
    public static volatile double brightness = 500;
    public static volatile double contrast = 500; 
    public static volatile double min = 0;
    public static volatile double max = 0;

    public static volatile boolean isRunning = false;

    public static volatile int r = 0;
    public static volatile int g = 0;
    public static volatile int b = 0;
    public static volatile int width = 400;
    public static volatile int height = 250;

    public volatile double inputExchangeFrame[][ ]= new double[400][250], outputExchangeFrame[][]= new double[400][250];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        seekBarBrightness = (SeekBar) findViewById(R.id.seekBarBrightness); 
        seekBarContrast = (SeekBar) findViewById(R.id.seekBarContrast);
        SeekBarGamma = (SeekBar) findViewById(R.id.seekBarGamma);

        newImage = Bitmap.createBitmap(width, height, BitmapConfig.ARGB_8888);              
        picture.setImageBitmap(newImage);


    }    

    @Override   
    public void onClick(View v) { 
        if(v==toggleButtonStartStop){
            if(toggleButtonStartStop.isChecked()==true){ 
                isRunning=true; 
                getFrame();
                calculateFrame();
                showFrame();
            }
            else{ 
                isRunning = false;
            }
        }
    }            
}

其他方法也在MainACtivity中声明: getFrame()方法:

private synchronized void getFrame(){
     inputThread = new Runnable(){
          public void run(){
               while(isRunning == true){

                   //inputFrame fron WIFI

                    inputExchangeFrameLock.lock();
                    //synchronized(inputExchangeFrame){
                         for(int x_1=0 ; x_1<width ; x_1++){
                              for(int y_1=0 ; y_1<height ; y_1++){
                                   inputExchangeFrame[x_1][y_1]=inputFrame[x_1][y_1];
                              }
                         }
                    //}
                   inputExchangeFrameLock.unlock();

                   try {                        
                        Thread.sleep(120);
                   } 
                   catch (InterruptedException e) {
                        e.printStackTrace();
                   }
              }
         }
     };new Thread(inputThread).start();
};

calculateFrame:

private synchronized void calculateFrame(){
     calculationThread = new Runnable(){
          public void run(){
               while(isRunning == true){    
               //get Data from InputThread to applicate several Filter
               inputExchangeFrameLock.lock();
               //synchronized(inputExchangeFrame){
                    for(int x_2=0 ; x_2<width ; x_2++){
                         for(int y_2=0 ; y_2<height ; y_2++){
                              calculationFrame[x_2][y_2]=inputExchangeFrame[x_2][y_2];
                         }
                    }
               //}
               inputExchangeFrameLock.unlock();

                 //Do some calculations on calculationFrame  

               outputExchangeFrameLock.lock();
               //synchronized(outputExchangeFrame){ 
                    for(int x_3=0 ; x_3<width ; x_3++){
                         for(int y_3=0 ; y_3<height ; y_3++){
                              outputExchangeFrame[x_3][y_3] = calculationFrame[x_3][y_3];
                         }
                    }
               //}
               outputExchangeFrameLock.unlock();
               }
          }
     }; new Thread(calculationThread).start();
};

showFrame():

private synchronized void showFrame(){
     outputThread = new Runnable(){
          public void 
               while(isRunning == true){
                    contrast =  seekBarContrast.getProgress() +1;
                    brightness = seekBarBrightness.getProgress() + 1;
                    gamma = seekBarGamma.getProgress() + 1;

                    outputExchangeFrameLock.lock();
                    //synchronized(outputExchangeFrame){
                    for(int x_4=0 ; x_4<width ; x_4++){
                         for(int y_4=0 ; y_4<height ; y_4++){
                              outputFrame[x_4][y_4] = outputExchangeFrame[x_4][y_4];
                          }
                     }  
                     //}
                     outputExchangeFrameLock.unlock();

                     for (int x_14=0 ; x_14<width ; x_14++){
                          for(int y_14=0; y_14<height; y_14++){

                             //Calculation of r,g,b  using gamma, brightness and contrast
                          }
                          synchronized(newImage){
                               newImage.setPixel(x_14, y_14, Color.rgb(r,g,b));
                          }
                     }

                     outputHandler.removeCallbacks(pictureUpdate);
                     outputHandler.post(pictureUpdate);

                     try {
                          Thread.sleep(50);
                     } 
                     catch (InterruptedException e) {
                          e.printStackTrace();
                     }
                }
           }
     }; new Thread(outputThread).start();   
};

和处理程序:

  

private Runnable pictureUpdate = new Runnable(){
       public void run(){   同步(newImage){   picture.setImageBitmap(newImage);
  }   }
  };

我知道很多文字。但我真的不知道从哪里开始搜索以及如何找到错误。

任何建议都会很棒!

感谢

迈克尔

1 个答案:

答案 0 :(得分:3)

您正在实现几个线程,并且您尝试执行的操作的顺序不是确定性的。

例如,可以在getFrame.Runable()。run()之前执行“showFrame.Runable()。run()”。

  1. “同步”关键字无效,因为当工作在单独的线程中关闭时。同步函数调用将返回,并且将释放锁定。
  2. “锁定”也无助于确保正确的顺序。
  3. 我的建议是使用AsyncTask,http://developer.android.com/reference/android/os/AsyncTask.html。你可以这样做:

    private class ProcessFrameTask extends AsyncTask {
    
     protected void doInBackground(Object... objs) {
         getFrame(); // Copy the frame
         calculateFrame(); // Do your magic
     }
    
     protected void onPostExecute(Long result) {
         showFrame(); // Post the result back to main thread
     }
    

    }

    没有多线程和合作,只有一个Worker线程完成所有工作,并将结果发布回主线程。