listview 可以暫時告一段落了。。。
下面說說android的多線程機制,講到多線程,就可以說道android有名的ANR(Application Not Responding)既應用程序未響應,觸發ANR的條件大致有兩個:1、在activity中超過5秒的時間未能響應下一個事件。2、BroadcastReceive超過10秒,這兩個條件都會觸發ANR。
下面模擬一個activity的ANR
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } }); }
運行效果:
未觸發:
觸發後:
當用戶使用時 出現這樣的體驗,可想而知會很蛋疼的。。。
有人就會問 爲什麼會有ANR這樣的機制。
其實android系統中所有的UI顯示都是在main線程中執行的,如果線程中有耗時操作時,線程中的其他UI組件就會等耗時結束時才能開始響應,所以爲了避免這樣的情況,android用handler將耗時操作放到子線程中執行,當結束時,將耗時操作的結果發回給主線程,所以這裏又要引入線程間通信的概念
額(⊙o⊙)… 到這裏感覺 新概念越寫越多了。。。。 沒事 慢慢解決麼。。。
這麼說感覺線程間通訊 很蛋疼 其實 也就調用一個方法而已。。。。
嘿嘿
不多說了 看代碼先
private Handler mHandler = new Handler() { //參數:Message相當於一種信息的載體,可以將子線程的數據傳到主線程中,也就是所謂的線程間通信了。。。 public void handleMessage(android.os.Message msg) {//該方法在主線程中執行,不信的話可以log的。。。 String result = (String) msg.obj;//從主線程傳來的數據 switch (msg.what)//what用於標記誰傳來的信息 { case 1: mTextView1.setText(result);//做UI組件的設置必須在主線程否則會報錯的。。。 break; case 2: mTextView2.setText(result); break; default: break; } } }; private TextView mTextView1; private TextView mTextView2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView1 = (TextView) findViewById(R.id.textView1); mTextView2 = (TextView) findViewById(R.id.textView2); Button button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(listener); Button button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(listener); } private OnClickListener listener = new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.button1: new Thread() { public void run() { // 模擬耗時操作 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } String result = "從網絡獲取的結果"; Message msg = new Message(); msg.what = 1; msg.obj = result; // 發送到main線程 mHandler.sendMessage(msg); // textView.setText(result); } }.start(); Log.e("MainActivity", "button1"); break; case R.id.button2: new Thread() { public void run() { // 模擬耗時操作 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } String result = "從數據庫獲取的結果"; Message msg = new Message(); msg.what = 2; msg.obj = result; // 發送到main線程 mHandler.sendMessage(msg); } }.start(); Log.e("MainActivity", "button2"); break; default: break; } } };
我會把源代碼 附加到文章的 佈局文件 就不寫了,佔地方。。。
運行結果:
handler 差不多就這些了。。。代碼的項目超過2mb 了 我放到51cto的網盤裏了
下面講講 post,其實view.post和handle.post這兩個方法差不多,都是在post方法中傳入一個實現了Runnable接口的對象,在這個對象的run方法中實現
private TextView mTextView; private Button mButton; class Listener implements OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { case R.id.button1: download(); break; default: break; } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = (Button) findViewById(R.id.button1); mButton.setOnClickListener(new Listener()); } public void download() { new PlayThread().start();//開啓子線程 } class PlayThread extends Thread { @Override public void run() {// 這是子線程 try { Thread.sleep(2000);//模擬從網絡下載數據的耗時操作 } catch (InterruptedException e) { e.printStackTrace(); } mButton.post(new Runnable()//這裏用的是view的post方法 {//這裏的內容將在主線程中顯示 @Override public void run() { mTextView.setText("yes 獲取到數據了~~~"); } }); } }
runOnUiThread(Runnable action)方法和handler.post(Runnable action)方法,這兩個方法的用法跟view.post(Runnable action)方法的用法一樣
runOnUiThread(Runnable action)是activity的方法,這裏的Runnable同樣是運行在主線程中的
handler.post(Runnable action)是handler中的方法,大同小異,當然如果大家能告訴我這之間的區別我也會洗耳恭聽的,相互學習麼,謝謝啦。。。