4

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

这里有一些代码:

主要活动:

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();
};

计算帧:

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();
};

显示帧():

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(){ synchronized(newImage){ picture.setImageBitmap(newImage);
} }
};

我知道那是很多文本。但我真的不知道从哪里开始搜索以及我可以做些什么来找到错误。

任何建议都会很棒!

谢谢

迈克尔

4

1 回答 1

3

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

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

  1. “同步”关键字没有帮助,因为当工作在单独的线程中停止时。同步函数调用将返回,锁将被释放。
  2. “锁”也无助于确保正确的顺序。

我的建议是使用 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 线程完成所有工作,并将结果发布回主线程。

于 2013-04-15T15:10:07.237 回答