標籤:
什麼是進程
一個進程是一個獨立(self contained)的運行環境,它可以看作一個程式或者一個應用。
什麼是線程
而線程是進程中執行的一個任務,Java運行環境是一個包含了不同累和程式的單一進程。線程可以被稱為輕量級進程。線程需要較少的資源來建立和駐留在進程中,並且可以共用進程中的資源。
Android線程
Android的線程,實際上和Java的多線程編程並沒有什麼本質上的不同。當我們需要執行一些耗時操作,比如說發起一條網路請求時,考慮到網速等其他原因,伺服器未必會立刻響應我們的請求,如果不將這類操作放在子線程中運行,就會導致主線程被阻塞住,從而影響使用者對軟體的正常使用。
線程的基本用法
Android多線程編程其實並不比Java多線程特殊,基本都是使用相同的文法。有兩種建立線程的方法:
一是建立一個繼承自Thread的類,然後重寫父類的run()方法,並在裡面編輯耗時邏輯即可,如:
1 public class MyThread extends Thread{2 @Override3 public void run(){4 //具體處理的邏輯5 }6 }
啟動這個線程的方法也很簡單,只需要new出MyThread的執行個體,然後調用它的start方法,這樣run()方法中的代碼就會在子線程中運行,如
new MyThread().start();
然而,使用繼承的耦合性比較高,更多的時候使用實現Runnable介面是一個不錯的選擇,如:
1 public class MyThread implements Runnable{2 @Override3 public void run(){4 //具體處理的邏輯5 }6 }
如果使用了這種寫法,啟動線程的方法也需要進行相應的改變,如:
MyThread myThread = new MyThread();new Thread(myThread).start();
可以看到,Thread的建構函式接收一個Runnable參數,而new出的MyThread正是一個實現了Runnable介面的對象,所以可以將它直接傳入到Thread的建構函式裡。接著調用Thread的start()方法,run()方法中的代碼就會在子線程中運行。
Android中的多線程
和許多其他的GUI庫一樣,Android的UI也是線程不安全的。也就是說,如果想要更新應用中的UI元素,則必須在主線程中進行,否則就會出現異常。
舉個例子,建立一個AndroidThreadTest的項目,然後修改activity中的代碼
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:id="@+id/change_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Change text"/> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello world" android:textSize="20sp"/> </RelativeLayout>
布局檔案中定義了兩個控制項,TextView用於在螢幕正中間顯示一個Hello World字串,Button用於改變TextView中顯示的內容。我們希望在點擊Button後可以把TextView中顯示的字串改成Nice to meey you.
接下來修改MainActivity中的代碼:
1 public class MainActivity extends Activity implements OnClickListener{ 2 3 private Button changeText; 4 private TextView text; 5 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main);10 text = (TextView)findViewById(R.id.text);11 changeText = (Button)findViewById(R.id.change_text);12 changeText.setOnClickListener(this);13 }14 15 @Override16 public boolean onCreateOptionsMenu(Menu menu) {17 // Inflate the menu; this adds items to the action bar if it is present.18 getMenuInflater().inflate(R.menu.main, menu);19 return true;20 }21 22 @Override23 public void onClick(View v) {24 // TODO Auto-generated method stub25 switch (v.getId()) {26 case R.id.change_text:27 new Thread(new Runnable() {28 29 @Override30 public void run() {31 // TODO Auto-generated method stub32 text.setText("Nice to meet you");33 }34 }).start();35 break;36 37 default:38 break;39 }40 }41 42 }
可以看到,在change text按鈕的點擊事件中開啟了一個子線程,然後在子線程中調用TextView的setText()方法去改變字串,代碼的邏輯非常簡單,但是就是按下按鈕然後更新文本,然後運行一下程式,可以發現程式不出所料的將會崩潰。
程式崩潰的原因是因為在子線程中更新UI所導致的,由此可以看到Android不允許在子線程進行UI操作。但有些時候我們必須在子進程中去執行一些耗時任務,然後根據任務的執行結果來更新相應的UI控制項,對於這種情況,就需要使用Android提供的一套非同步訊息處理機制了。
Android多線程編程(一)——多線程基礎