Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/182.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 为什么我的HandlerThread会更新UI_Android_Multithreading - Fatal编程技术网

Android 为什么我的HandlerThread会更新UI

Android 为什么我的HandlerThread会更新UI,android,multithreading,Android,Multithreading,我目前正在用一个简单的摄像头示例在Android中练习HandlerThread,问题是如果我在onCreate中创建我的CameraController对象,并向处理线程发送一条消息,以便处理我的openCamera()方法(其中包含直接的UI更新代码) 它允许我更新用户界面,尽管我不应该被允许这样做,因为从技术上讲,我应该在一个不同的线程中 public class MainActivity extends AppCompatActivity implements Handler.Callb

我目前正在用一个简单的摄像头示例在Android中练习
HandlerThread
,问题是如果我在
onCreate
中创建我的
CameraController
对象,并向处理线程发送一条消息,以便处理我的
openCamera()
方法(其中包含直接的UI更新代码)

它允许我更新用户界面,尽管我不应该被允许这样做,因为从技术上讲,我应该在一个不同的线程中

public class MainActivity extends AppCompatActivity implements Handler.Callback {

private ToggleButton toggleButton;
private TextView textView;
private CameraController mTestCam;

//generate messages
private static final int MSG_OPEN_CAM = 0;
private static final int MSG_CLOSE_CAM = 1;
private static final int MSG_OPEN_FLASH= 2;
private static final int MSG_CLOSE_FLASH = 3;
//verify
private static final int MSG_OPEN_CAM_DONE = 4; // nu trebuie
private static final int MSG_CLOSE_CAM_DONE = 5;
private static final int MSG_OPEN_FLASH_DONE= 6;
private static final int MSG_CLOSE_FLASH_DONE= 7;

//used for MainActivity HandleMessage
protected Handler mHandler;

//camera controler thread
private CameraControllerThread mCameraControlThread;



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


    //android marshmallow - in order for service to run you need runtime permissions
    //testCam.openCamera(); //moved to method

    toggleButton = (ToggleButton) findViewById(R.id.toggleButton);
    textView = (TextView) findViewById(R.id.textView_text);

    mHandler = new Handler(this);
    mCameraControlThread = new CameraControllerThread("Camera Control Thread");
    mCameraControlThread.start();

    //moved to onStart
    mTestCam = new CameraController();
    Message openCameraMsg = mCameraControlThread.mWorkerHandler.obtainMessage(this.MSG_OPEN_CAM);
    openCameraMsg.sendToTarget();


    toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {

            if(isChecked){

                mTestCam = new CameraController();
                Message openCameraMsg = mCameraControlThread.mWorkerHandler
                        .obtainMessage(MSG_OPEN_CAM);
                openCameraMsg.sendToTarget();

                //mTestCam.openFlash();
            } else {
                //close flash
                //mTestCam.stopFlash();
            }

        }
    });

}

private void openCamera(){
    synchronized (mTestCam){
        mTestCam.openCamera();
    }
    Toast.makeText(this, "This is my text", Toast.LENGTH_LONG).show();
    textView.setVisibility(View.VISIBLE);
    textView.setText("Camera Open");
}

@Override
public boolean handleMessage(Message message) {
    return false;
}


private class CameraControllerThread extends HandlerThread implements Handler.Callback{

    protected Handler mWorkerHandler;

    public CameraControllerThread(String name){
        super(name);
    }

    @Override
    protected void onLooperPrepared() {
        mWorkerHandler = new Handler(getLooper(), this);
    }

    @Override
    public boolean handleMessage(Message message) {

        switch(message.what){
            case MSG_OPEN_CAM:
                openCamera();
                break;
        }

        return true;
    }
 }
}
如果我移动code
onCheckedChanged
方法(它在下面的代码片段中有注释),应用程序将崩溃,说明我正在尝试从其他线程更新UI线程

public class MainActivity extends AppCompatActivity implements Handler.Callback {

private ToggleButton toggleButton;
private TextView textView;
private CameraController mTestCam;

//generate messages
private static final int MSG_OPEN_CAM = 0;
private static final int MSG_CLOSE_CAM = 1;
private static final int MSG_OPEN_FLASH= 2;
private static final int MSG_CLOSE_FLASH = 3;
//verify
private static final int MSG_OPEN_CAM_DONE = 4; // nu trebuie
private static final int MSG_CLOSE_CAM_DONE = 5;
private static final int MSG_OPEN_FLASH_DONE= 6;
private static final int MSG_CLOSE_FLASH_DONE= 7;

//used for MainActivity HandleMessage
protected Handler mHandler;

//camera controler thread
private CameraControllerThread mCameraControlThread;



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


    //android marshmallow - in order for service to run you need runtime permissions
    //testCam.openCamera(); //moved to method

    toggleButton = (ToggleButton) findViewById(R.id.toggleButton);
    textView = (TextView) findViewById(R.id.textView_text);

    mHandler = new Handler(this);
    mCameraControlThread = new CameraControllerThread("Camera Control Thread");
    mCameraControlThread.start();

    //moved to onStart
    mTestCam = new CameraController();
    Message openCameraMsg = mCameraControlThread.mWorkerHandler.obtainMessage(this.MSG_OPEN_CAM);
    openCameraMsg.sendToTarget();


    toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {

            if(isChecked){

                mTestCam = new CameraController();
                Message openCameraMsg = mCameraControlThread.mWorkerHandler
                        .obtainMessage(MSG_OPEN_CAM);
                openCameraMsg.sendToTarget();

                //mTestCam.openFlash();
            } else {
                //close flash
                //mTestCam.stopFlash();
            }

        }
    });

}

private void openCamera(){
    synchronized (mTestCam){
        mTestCam.openCamera();
    }
    Toast.makeText(this, "This is my text", Toast.LENGTH_LONG).show();
    textView.setVisibility(View.VISIBLE);
    textView.setText("Camera Open");
}

@Override
public boolean handleMessage(Message message) {
    return false;
}


private class CameraControllerThread extends HandlerThread implements Handler.Callback{

    protected Handler mWorkerHandler;

    public CameraControllerThread(String name){
        super(name);
    }

    @Override
    protected void onLooperPrepared() {
        mWorkerHandler = new Handler(getLooper(), this);
    }

    @Override
    public boolean handleMessage(Message message) {

        switch(message.what){
            case MSG_OPEN_CAM:
                openCamera();
                break;
        }

        return true;
    }
 }
}
我想我的问题是-为什么我实例化我的
CameraController
并从
onCreate
发送消息-它允许我更新UI-当我从
onCheckedChangeListener
执行同样的操作时,它不允许我?

引用:

[从UI线程外部访问Android UI toolkit]可能会导致未定义和意外的行为,这可能很难且耗时地跟踪


任何事情都可能在竞争条件之后发生。

扩展
HandlerThread
在大多数情况下都是多余的:只需创建新的
HT
start()
它并创建一个
新的处理程序(HT.getLooper())
,这就是我在教程中学习的内容:)-谢谢您的提示,在这种情况下,如何在启动应用程序时启动相机?通常我需要在onCreate或onStart@AlexPRY您可以在任何喜欢的线程中初始化相机,例如在主线程或CameraController线程中的onStart内部。问题是在主线程外显示Toast和更新TextView。例如,您可以在
活动中执行。runOnUiThread()
谢谢,我会考虑你的建议——事实上,我注意到了其他一些奇怪的行为,当我从不同的线程扰乱UI时——我想了解的是我的问题发生的原因——但由于文档中指出可能会发生意外行为——我猜这就是他们所说的:)