Android线程的学习 之二

来源:互联网 发布:九洲盛世网络竞技杭州 编辑:程序博客网 时间:2024/06/04 08:40
在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行!
   1.当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
   2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。

现在来看一个例子,模拟从网络获取数据,加载到ListView的过程:

  1. public class ListProgressDemo extends ListActivity 
  2.  
  3.     @Override 
  4.     public void onCreate(Bundle savedInstanceState) 
  5.         super.onCreate(savedInstanceState); 
  6.         setContentView(R.layout.listprogress); 
  7.  
  8.         ((Button) findViewById(R.id.load_Handler)).setOnClickListener(new View.OnClickListener(){ 
  9.  
  10.             @Override 
  11.             public void onClick(View view) 
  12.                 data null
  13.                 data new ArrayList<String>(); 
  14.  
  15.                 adapter null
  16.  
  17.                 showDialog(PROGRESS_DIALOG); 
  18.                 new ProgressThread(handler, data).start(); 
  19.             
  20.         }); 
  21.     
  22.  
  23.     @Override 
  24.     protected Dialog onCreateDialog(int id) 
  25.         switch(id) 
  26.         case PROGRESS_DIALOG: 
  27.                  return ProgressDialog.show(this"" 
  28.                    "Loading. Please wait..."true); 
  29.  
  30.         defaultreturn null
  31.         
  32.     
  33.  
  34.     private class ProgressThread extends Thread 
  35.  
  36.         private Handler handler; 
  37.         private ArrayList<String> data; 
  38.  
  39.         public ProgressThread(Handler handler, ArrayList<String> data) 
  40.             this.handler handler; 
  41.             this.data data; 
  42.         
  43.  
  44.         @Override 
  45.         public void run() 
  46.             for (int i=0i<8i++) 
  47.                 data.add("ListItem"); //后台数据处理
  48.                 try 
  49.                     Thread.sleep(100); 
  50.                 }catch(InterruptedException e) 
  51.                      
  52.                     Message msg handler.obtainMessage(); 
  53.                     Bundle new Bundle(); 
  54.                     b.putInt("state"STATE_ERROR); 
  55.                     msg.setData(b); 
  56.                     handler.sendMessage(msg);  
  57.                      
  58.                 
  59.             
  60.             Message msg handler.obtainMessage(); 
  61.             Bundle new Bundle(); 
  62.             b.putInt("state"STATE_FINISH); 
  63.             msg.setData(b); 
  64.             handler.sendMessage(msg); 
  65.         
  66.          
  67.     
  68.  
  69.     // 此处甚至可以不需要设置Looper,因为Handler默认就使用当前线程的Looper
  70.     private final Handler handler new Handler(Looper.getMainLooper()) {
  71.  
  72.         public void handleMessage(Message msg) //处理Message,更新ListView
  73.             int state msg.getData().getInt("state"); 
  74.             switch(state){ 
  75.                 case STATE_FINISH: 
  76.                     dismissDialog(PROGRESS_DIALOG); 
  77.                     Toast.makeText(getApplicationContext(), 
  78.                             "加载完成!"
  79.                             Toast.LENGTH_LONG) 
  80.                          .show(); 
  81.  
  82.                     adapter new ArrayAdapter<String>(getApplicationContext(), 
  83.                             android.R.layout.simple_list_item_1, 
  84.                             data ); 
  85.                              
  86.                     setListAdapter(adapter); 
  87.  
  88.                     break
  89.  
  90.                 case STATE_ERROR: 
  91.                    dismissDialog(PROGRESS_DIALOG); 
  92.                    Toast.makeText(getApplicationContext(), 
  93.                            "处理过程发生错误!"
  94.                            Toast.LENGTH_LONG) 
  95.                         .show(); 
  96.  
  97.                    adapter new ArrayAdapter<String>(getApplicationContext(), 
  98.                            android.R.layout.simple_list_item_1, 
  99.                            data ); 
  100.                             
  101.                       setListAdapter(adapter); 
  102.  
  103.                       break
  104.  
  105.                default
  106.  
  107.             
  108.         
  109.     }; 
  110.  
  111.  
  112.     private ArrayAdapter<String> adapter; 
  113.     private ArrayList<String> data; 
  114.  
  115.     private static final int PROGRESS_DIALOG 1
  116.     private static final int STATE_FINISH 1
  117.     private static final int STATE_ERROR -1

这个例子,我自己写完后觉得还是有点乱,要稍微整理才能看明白线程间交互的过程以及数据的前后变化。随后了解到AsyncTask类,相应修改后就很容易明白了!

 

2.3 AsyncTask

AsyncTask版:
  1. ((Button) findViewById(R.id.load_AsyncTask)).setOnClickListener(new View.OnClickListener(){ 
  2.  
  3.     @Override 
  4.     public void onClick(View view) 
  5.         data null
  6.         data new ArrayList<String>(); 
  7.  
  8.         adapter null
  9.  
  10.         //显示ProgressDialog放到AsyncTask.onPreExecute()里 
  11.         //showDialog(PROGRESS_DIALOG); 
  12.         new ProgressTask().execute(data); 
  13.     
  14. }); 
  15.  
  16. private class ProgressTask extends AsyncTask<ArrayList<String>, Void, Integer> 
  17.  
  18.  
  19. @Override 
  20. protected void onPreExecute() 
  21.     // 先显示ProgressDialog
  22.     showDialog(PROGRESS_DIALOG); 
  23.  
  24.  
  25. @Override 
  26. protected Integer doInBackground(ArrayList<String>... datas) 
  27.     ArrayList<String> data datas[0]; 
  28.     for (int i=0i<8i++) 
  29.         data.add("ListItem"); 
  30.     
  31.     return STATE_FINISH; 
  32.  
  33.  
  34. @Override 
  35. protected void onPostExecute(Integer result) 
  36.     int state result.intValue(); 
  37.     switch(state){ 
  38.     case STATE_FINISH: 
  39.         dismissDialog(PROGRESS_DIALOG); 
  40.         Toast.makeText(getApplicationContext(), 
  41.                 "加载完成!"
  42.                 Toast.LENGTH_LONG) 
  43.              .show(); 
  44.  
  45.         adapter new ArrayAdapter<String>(getApplicationContext(), 
  46.                 android.R.layout.simple_list_item_1, 
  47.                 data ); 
  48.                  
  49.         setListAdapter(adapter); 
  50.  
  51.         break
  52.          
  53.     case STATE_ERROR: 
  54.        dismissDialog(PROGRESS_DIALOG); 
  55.        Toast.makeText(getApplicationContext(), 
  56.                "处理过程发生错误!"
  57.                Toast.LENGTH_LONG) 
  58.             .show();
  59.  
  60.        adapter new ArrayAdapter<String>(getApplicationContext(), 
  61.                android.R.layout.simple_list_item_1, 
  62.                data );
  63.  
  64.           setListAdapter(adapter);
  65.  
  66.           break;
  67.  
  68.    default:
  69.  
  70.    }
  71. }

   Android另外提供了一个工具类:AsyncTask。它使得UIthread的使用变得异常简单。它使创建需要与用户界面交互的长时间运行的任务变得更简单,不需要借助线程和Handler即可实现。

    1) 子类化AsyncTask
    2) 实现AsyncTask中定义的下面一个或几个方法
        onPreExecute()开始执行前的准备工作;
        doInBackground(Params...)开始执行后台处理,可以调用publishProgress方法来更新实时的任务进度;
        onProgressUpdate(Progress...) 在publishProgress方法被调用后,UIthread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
       onPostExecute(Result)执行完成后的操作,传送结果给UI 线程。
 
       这4个方法都不能手动调用。而且除了doInBackground(Params...)方法,其余3个方法都是被UI线程所调用的,所以要求:
       1) AsyncTask的实例必须在UIthread中创建;
       2) AsyncTask.execute方法必须在UIthread中调用;
       
   同时要注意:该task只能被执行一次,否则多次调用时将会出现异常。而且是不能手动停止的,这一点要注意,看是否符合你的需求!
 
   在使用过程中,发现AsyncTask的构造函数的参数设置需要看明白:AsyncTask<Params,Progress, Result>
   Params对应doInBackground(Params...)的参数类型。而newAsyncTask().execute(Params...params),就是传进来的Params数据,你可以execute(data)来传送一个数据,或者execute(data1,data2, data3)这样多个数据。
   Progress对应onProgressUpdate(Progress...)的参数类型;
   Result对应onPostExecute(Result)的参数类型。
   当以上的参数类型都不需要指明某个时,则使用Void,注意不是void。不明白的可以参考上面的例子,或者APIDoc里面的例子。
 
----------------
本文的相当内容摘录于《浅析Android线程模型一 ---转》,但对于Message机制的流程理解则在参考《android中Message机制的灵活应用》后修改了!
转至 http://android.blog.51cto.com/268543/343823
0 0
原创粉丝点击