Android-Looper之后的代码
我有一个子线程在运行,无限地执行任务。我希望(1)不断地将数据发送回UI线程,(2)偶尔将数据(对应于按钮)发送到子线程以暂停/继续无限任务。我的问题是,子线程卡在活套中,这意味着任务无法执行 我的问题是:如何让子线程从UI线程接收消息而不阻塞无限任务 这就是我到目前为止所做的: 对于任务(1),我在UI线程中有一个处理程序,它可以工作,在子线程中有一个无限循环,它可以发回一条消息,该消息本身就可以工作 在UI线程中:Android-Looper之后的代码,android,multithreading,looper,Android,Multithreading,Looper,我有一个子线程在运行,无限地执行任务。我希望(1)不断地将数据发送回UI线程,(2)偶尔将数据(对应于按钮)发送到子线程以暂停/继续无限任务。我的问题是,子线程卡在活套中,这意味着任务无法执行 我的问题是:如何让子线程从UI线程接收消息而不阻塞无限任务 这就是我到目前为止所做的: 对于任务(1),我在UI线程中有一个处理程序,它可以工作,在子线程中有一个无限循环,它可以发回一条消息,该消息本身就可以工作 在UI线程中: mMainHandler = new Handler() { pub
mMainHandler = new Handler() {
public void handleMessage(Message msg) {
Bundle b;
b = msg.getData();
if (msg.what==1)
Log.i("main", "from child (running) - " + b.getBoolean("running"));
else if (msg.what == 2)
Log.i("main", "from child (count) - " + b.getInt("count"));
}
};
private void sendRunning(boolean running) {
if (mChildHandler != null) {
Bundle b = new Bundle(1);
b.putBoolean("running", running);
Message msg = mChildHandler.obtainMessage();
msg.what = 1;
msg.setData(b);
mChildHandler.sendMessage(msg);
}
}
在子线程中(当前使用虚拟任务,直到我完成框架):
对于任务(2),我在UI线程中有一个方法,对应于向子线程发送消息的按钮按下,该方法有效;子线程中有一个处理程序,该处理程序自身有效
在UI线程中:
mMainHandler = new Handler() {
public void handleMessage(Message msg) {
Bundle b;
b = msg.getData();
if (msg.what==1)
Log.i("main", "from child (running) - " + b.getBoolean("running"));
else if (msg.what == 2)
Log.i("main", "from child (count) - " + b.getInt("count"));
}
};
private void sendRunning(boolean running) {
if (mChildHandler != null) {
Bundle b = new Bundle(1);
b.putBoolean("running", running);
Message msg = mChildHandler.obtainMessage();
msg.what = 1;
msg.setData(b);
mChildHandler.sendMessage(msg);
}
}
在子线程中:
Looper.prepare();
mChildHandler = new Handler() {
public void handleMessage(Message msg) {
Bundle b;
if (msg.what==1){
b = msg.getData();
running = b.getBoolean("running");
Log.i(INNER_TAG, "from main (running) - " + b.getBoolean("running"));
Log.i(INNER_TAG, "running - " + running);
try {
Message toMain = mMainHandler.obtainMessage();
toMain.what = 1;
toMain.setData(b);
mMainHandler.sendMessage(toMain);
} finally {}
}
}
};
Looper.loop();
这些场景中的每一个都可以单独工作,但问题是要同时尝试这两个场景。如果我将无限任务放在Looper.loop()之后,它永远不会到达。如果我将它放在Looper.prepare()之前,它将运行一次。如果我把它和活套放在一起,它仍然只运行一次
任何想法都将不胜感激:)
以下是我的完整代码(减去包/导入),以供参考:
public class MainActivity extends Activity {
Thread thread;
private Handler mMainHandler, mChildHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainHandler = new Handler() {
public void handleMessage(Message msg) {
Bundle b;
b = msg.getData();
if (msg.what==1)
Log.i("main", "from child (running) - " + b.getBoolean("running"));
else if (msg.what == 2)
Log.i("main", "from child (count) - " + b.getInt("count"));
}
};
thread = new ChildThread();
thread.start();
// Get a reference to the button
Button buttonStart = (Button)findViewById(R.id.btnStart);
Button buttonStop = (Button)findViewById(R.id.btnStop);
// Set the click listener to run my code
buttonStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,
"Starting...", Toast.LENGTH_SHORT).show();
sendRunning(true);
}
});
buttonStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,
"Stopping...", Toast.LENGTH_SHORT).show();
sendRunning(false);
}
});
}
private void sendRunning(boolean running) {
if (mChildHandler != null) {
Bundle b = new Bundle(1);
b.putBoolean("running", running);
Message msg = mChildHandler.obtainMessage();
msg.what = 1;
msg.setData(b);
mChildHandler.sendMessage(msg);
}
}
@Override
protected void onDestroy() {
Log.i("tag", "stop looping the child thread's message queue");
mChildHandler.getLooper().quit();
super.onDestroy();
}
class ChildThread extends Thread {
private static final String INNER_TAG = "ChildThread";
private boolean running = true;
final int maxCount = 10;
final int minCount = 0;
public int curCount = minCount;
private int up = 1;
public void run() {
while (true) {
if (running) {
try {
curCount += up;
if (curCount == maxCount)
up = -1;
else if (curCount == minCount)
up = 1;
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e("", "local Thread error", e);
}
Bundle b = new Bundle(1);
b.putInt("count", curCount);
Message toMain = mMainHandler.obtainMessage();
toMain.what = 2;
toMain.setData(b);
mMainHandler.sendMessage(toMain);
}
this.setName("child");
Looper.prepare();
mChildHandler = new Handler() {
public void handleMessage(Message msg) {
Bundle b;
if (msg.what==1){
b = msg.getData();
running = b.getBoolean("running");
Log.i(INNER_TAG, "from main (running) - " + b.getBoolean("running"));
Log.i(INNER_TAG, "running - " + running);
try {
Message toMain = mMainHandler.obtainMessage();
toMain.what = 1;
toMain.setData(b);
mMainHandler.sendMessage(toMain);
} finally {}
}
}
};
Log.i(INNER_TAG, "Child handler is bound to - " +
mChildHandler.getLooper().getThread().getName());
Looper.loop();
}
}
}
}只需使用Intent service,而不使用此线程,这样您就可以管理更新的所有UI,以及您想在Intent service中使用的UI做什么—一个广播接收器正在使用,处理线程和感染您的UI非常容易—您的UI在后台进程运行时不受控制或锁定 为了避免这种情况,我最终只是对线程使用了一个可变时间。谢谢你的建议。旁注:我花了一段时间研究并试图找出如何使用线程,佩奇把它布置得非常好。页面向我展示了如何使用捆绑包在线程之间交换数据。如果可能,请避免无限期地运行线程。。。