在寫一個小應用的時候,我接觸到了一個關於Handler和Thread以及runnable的問題,問了群裡各種人都解決不了,然後查閱大量資料,終於有些瞭解,現在發上來和大家分享。
主要是關於,Thread和Runnable的區別,以及他們在使用Handler時造成的影響~,我先上代碼
下面這個是錯誤的代碼~下面的代碼只要執行到handler中更新UI的部分就會報null 指標錯誤~線程處用的Thread
public class MainActivity extends Activity {TextView text1, text2;Button button;myThread th;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);text1 = (TextView)findViewById(R.id.text1);text2 = (TextView)findViewById(R.id.text2);button = (Button)findViewById(R.id.button1);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubth = new myThread();th.start();}});}Handler myHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubswitch (msg.what) {case 1:System.out.println("-----------1--------------");System.out.println(msg.getData().getString("s1"));System.out.println(msg.getData().getString("s2"));try{ text1.setText(msg.getData().getString("s1")); text2.setText(msg.getData().getString("s1"));}catch(Exception e){e.printStackTrace();}break;default:break;}super.handleMessage(msg);}};}class myThread extends Thread{String s1, s2;MainActivity ma = new MainActivity();public void run(){ s1 = "fsdfsgfdsgdfgfdgdhshshs"; s2 = "fsfsdgdshdhdshrehreherh"; Message msg = new Message(); msg.what = 1; Bundle bundle = new Bundle(); bundle.putString("s1", s1); bundle.putString("s2", s2); msg.setData(bundle); ma.myHandler.sendMessage(msg);}}
上面這段代碼,沒給注釋,但是很簡單,相信大家都能看懂~,這段代碼是錯誤的。
下面給大家上正確的代碼~線程處用的Runnable
public class MainActivity extends Activity {TextView text1, text2;Button button;Thread th;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);text1 = (TextView)findViewById(R.id.text1);text2 = (TextView)findViewById(R.id.text2);button = (Button)findViewById(R.id.button1);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubth = new Thread(runnable);th.start();}});}Handler myHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubswitch (msg.what) {case 1:System.out.println("-----------1--------------");System.out.println(msg.getData().getString("s1"));System.out.println(msg.getData().getString("s2"));try{ text1.setText(msg.getData().getString("s1")); text2.setText(msg.getData().getString("s1"));}catch(Exception e){e.printStackTrace();}break;default:break;}super.handleMessage(msg);}};Runnable runnable = new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stub String s1 = "fsdfsgfdsgdfgfdgdhshshs"; String s2 = "fsfsdgdshdhdshrehreherh"; Message msg = new Message(); msg.what = 1; Bundle bundle = new Bundle(); bundle.putString("s1", s1); bundle.putString("s2", s2); msg.setData(bundle); MainActivity.this.myHandler.sendMessage(msg);}};}
這是正確的代碼,能正確更新UI。
找到問題以後,我又做了幾個小實驗,發現,其實用Thread也是可以的,也是可以更新UI的,就像這樣
public class MainActivity extends Activity {TextView text1, text2;Button button;myThread th;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);text1 = (TextView)findViewById(R.id.text1);text2 = (TextView)findViewById(R.id.text2);button = (Button)findViewById(R.id.button1);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubth = new myThread();th.start();}});}Handler myHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubswitch (msg.what) {case 1:System.out.println("-----------1--------------");System.out.println(msg.getData().getString("s1"));System.out.println(msg.getData().getString("s2"));try{ text1.setText(msg.getData().getString("s1")); text2.setText(msg.getData().getString("s1"));}catch(Exception e){e.printStackTrace();}break;default:break;}super.handleMessage(msg);}};class myThread extends Thread{public void run() {// TODO Auto-generated method stub String s1 = "fsdfsgfdsgdfgfdgdhshshs"; String s2 = "fsfsdgdshdhdshrehreherh"; Message msg = new Message(); msg.what = 1; Bundle bundle = new Bundle(); bundle.putString("s1", s1); bundle.putString("s2", s2); msg.setData(bundle); MainActivity.this.myHandler.sendMessage(msg);}}}
到這,不知道大家發現問題在哪沒有?
據我所瞭解~Thread和Runnable的區別如下:
如果然一個線程實現Runnable介面,當調用這個線程對象開闢多線程時,可以讓這些線程調用同一變數~,(說白了就是,我主線程和拋出的子線程都可以用你主線程的變數了)
若這個線程類是繼承自Thread類而來,則通過內部類實現上述功能,利用的就是內部類可任意訪問外部類這一特性(這段說的就是我3段代碼的最後1段)。
好了,完了,就這麼多,希望對大家有協助