在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行!
1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。
1)
子类化AsyncTask
2)
实现AsyncTask中定义的下面一个或几个方法
onPreExecute() 开始执行前的准备工作;
doInBackground(Params...) 开始执行后台处理,可以调用publishProgress方法来更新实时的任务进度;
onProgressUpdate(Progress...)
在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result) 执行完成后的操作,传送结果给UI 线程。
这4个方法都不能手动调用。而且除了doInBackground(Params...)方法,其余3个方法都是被UI线程所调用的,所以要求:
1) AsyncTask的实例必须在UI thread中创建;
2) AsyncTask.execute方法必须在UI thread中调用;
同时要注意:该task只能被执行一次,否则多次调用时将会出现异常。而且是不能手动停止的,这一点要注意,看是否符合你的需求!
在使用过程中,发现AsyncTask的构造函数的参数设置需要看明白:
AsyncTask<Params, Progress, Result>
Params对应doInBackground(Params...)的参数类型。而new AsyncTask().execute(Params... params),就是传进来的Params数据,你可以execute(data)来传送一个数据,或者execute(data1, data2, data3)这样多个数据。
Progress对应onProgressUpdate(Progress...)的参数类型;
Result对应onPostExecute(Result)的参数类型。
当以上的参数类型都不需要指明某个时,则使用Void,注意不是void。不明白的可以参考上面的例子,或者API Doc里面的例子。
现在来看一个例子,模拟从网络获取数据,加载到ListView的过程:
- public
class ListProgressDemo extends ListActivity { -
-
@Override -
public void onCreate(Bundle savedInstanceState) { -
super.onCreate(savedInstanceState); -
setContentView(R.layout.listprogress); -
-
((Button) findViewById(R.id.load_Handler)).setOnClickListener(new View.OnClickListener(){ -
-
@Override -
public void onClick(View view) { -
data = null; -
data = new ArrayList<String>(); -
-
adapter = null; -
-
showDialog(PROGRESS_DIALOG); -
new ProgressThread(handler, data).start(); -
} -
}); -
} -
-
@Override -
protected Dialog onCreateDialog(int id) { -
switch(id) { -
case PROGRESS_DIALOG: -
return ProgressDialog.show(this, "", -
"Loading. Please wait...", true); -
-
default: return null; -
} -
} -
-
private class ProgressThread extends Thread { -
-
private Handler handler; -
private ArrayList<String> data; -
-
public ProgressThread(Handler handler, ArrayList<String> data) { -
this.handler = handler; -
this.data = data; -
} -
-
@Override -
public void run() { -
for (int i=0; i<8; i++) { -
data.add("ListItem"); //后台数据处理 -
try { -
Thread.sleep(100); -
}catch(InterruptedException e) { -
-
Message msg = handler.obtainMessage(); -
Bundle b = new Bundle(); -
b.putInt("state", STATE_ERROR); -
msg.setData(b); -
handler.sendMessage(msg); -
-
} -
} -
Message msg = handler.obtainMessage(); -
Bundle b = new Bundle(); -
b.putInt("state", STATE_FINISH); -
msg.setData(b); -
handler.sendMessage(msg); -
} -
-
} -
-
// 此处甚至可以不需要设置Looper,因为Handler默认就使用当前线程的Looper -
private final Handler handler = new Handler(Looper.getMainLooper()) { -
-
public void handleMessage(Message msg) { // 处理Message,更新ListView -
int state = msg.getData().getInt("state"); -
switch(state){ -
case STATE_FINISH: -
dismissDialog(PROGRESS_DIALOG); -
Toast.makeText(getApplicationContext(), -
"加载完成!", -
Toast.LENGTH_LONG) -
.show(); -
-
adapter = new ArrayAdapter<String>(getApplicationContext(), -
android.R.layout.simple_list_item_1, -
data ); -
-
setListAdapter(adapter); -
-
break; -
-
case STATE_ERROR: -
dismissDialog(PROGRESS_DIALOG); -
Toast.makeText(getApplicationContext(), -
"处理过程发生错误!", -
Toast.LENGTH_LONG) -
.show(); -
-
adapter = new ArrayAdapter<String>(getApplicationContext(), -
android.R.layout.simple_list_item_1, -
data ); -
-
setListAdapter(adapter); -
-
break; -
-
default: -
-
} -
} -
}; -
-
-
private ArrayAdapter<String> adapter; -
private ArrayList<String> data; -
-
private static final int PROGRESS_DIALOG = 1; -
private static final int STATE_FINISH = 1; -
private static final int STATE_ERROR = -1; - }
这个例子,我自己写完后觉得还是有点乱,要稍微整理才能看明白线程间交互的过程以及数据的前后变化。随后了解到AsyncTask类,相应修改后就很容易明白了!
2.3 AsyncTask
AsyncTask版:
- ((Button)
findViewById(R.id.load_AsyncTask)).setOnClickListener(new View.OnClickListener(){ -
-
@Override -
public void onClick(View view) { -
data = null; -
data = new ArrayList<String>(); -
-
adapter = null; -
-
//显示ProgressDialog放到AsyncTask.onPreExecute()里 -
//showDialog(PROGRESS_DIALOG); -
new ProgressTask().execute(data); -
} - });
-
- private
class ProgressTask extends AsyncTask<ArrayList<String>, Void, Integer> { -
-
- @Override
- protected
void onPreExecute() { -
// 先显示ProgressDialog -
showDialog(PROGRESS_DIALOG); - }
-
-
- @Override
- protected
Integer doInBackground(ArrayList<String>... datas) { -
ArrayList<String> data = datas[0]; -
for (int i=0; i<8; i++) { -
data.add("ListItem"); -
} -
return STATE_FINISH; - }
-
-
- @Override
- protected
void onPostExecute(Integer result) { -
int state = result.intValue(); -
switch(state){ -
case STATE_FINISH: -
dismissDialog(PROGRESS_DIALOG); -
Toast.makeText(getApplicationContext(), -
"加载完成!", -
Toast.LENGTH_LONG) -
.show(); -
-
adapter = new ArrayAdapter<String>(getApplicationContext(), -
android.R.layout.simple_list_item_1, -
data ); -
-
setListAdapter(adapter); -
-
break; -
-
case STATE_ERROR: -
dismissDialog(PROGRESS_DIALOG); -
Toast.makeText(getApplicationContext(), -
"处理过程发生错误!", -
Toast.LENGTH_LONG) -
.show(); -
-
adapter = new ArrayAdapter<String>(getApplicationContext(), -
android.R.layout.simple_list_item_1, -
data ); -
-
setListAdapter(adapter); -
-
break; -
-
default: -
-
} - }
----------------
本文的相当内容摘录于《
浅析Android线程模型一 --- 转》,但对于Message机制的流程理解则在参考《
android中Message机制的灵活应用》后修改了!