在Android開發中,我們或許會碰到這么一種業務需求,一項任務分成幾個子任務,子任務按順序先后執行,子任務全部執行完后,這項任務才算成功。那么,利用幾個子線程順序執行是可以達到這個目的的,但是每個線程必須去手動控制,而且得在一個子線程執行完后,再開啟另一個子線程。或者,全部放到一個線程中讓其順序執行。這樣都可以做到,但是,如果這是一個后台任務,就得放到Service里面,由於Service和Activity是同級的,所以,要執行耗時任務,就得在Service里面開子線程來執行。那么,有沒有一種簡單的方法來處理這個過程呢,答案就是IntentService。
IntentService是繼承於Service並處理異步請求的一個類,在IntentService內有一個工作線程來處理耗時操作,啟動IntentService的方式和啟動傳統Service一樣,同時,當任務執行完后,IntentService會自動停止,而不需要我們去手動控制。另外,可以啟動IntentService多次,而每一個耗時操作會以工作隊列的方式在IntentService的onHandleIntent回調方法中執行,並且,每次只會執行一個工作線程,執行完第一個再執行第二個,以此類推。
所有請求都在一個單線程中,不會阻塞應用程序的主線程(UI Thread),同一時間只處理一個請求。
那么,用IntentService有什么好處呢?首先,我們省去了在Service中手動開線程的麻煩,第二,當操作完成時,我們不用手動停止Service,第三,it's so easy to use!
下面我們來看個例子:
在main.xml文件中:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" > 10 11 <Button 12 android:id="@+id/button1" 13 android:layout_width="fill_parent" 14 android:layout_height="wrap_content" 15 android:text="下載圖片" /> 16 17 </RelativeLayout>
在MainActivity.java文件中:
1 public class MainActivity extends Activity { 2 3 private Button button; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 button = (Button) findViewById(R.id.button1); 10 button.setOnClickListener(new OnClickListener() { 11 12 public void onClick(View v) { 13 // TODO 自動生成的方法存根 14 Intent service = new Intent(MainActivity.this, IntentSer.class); 15 startService(service); 16 } 17 }); 18 } 19 20 @Override 21 public boolean onCreateOptionsMenu(Menu menu) { 22 // Inflate the menu; this adds items to the action bar if it is present. 23 getMenuInflater().inflate(R.menu.main, menu); 24 return true; 25 } 26 27 }
在IntentSer.java文件中:
1 public class IntentSer extends IntentService { 2 3 private String path_url = "http://t1.ituba.cc/uploads/allimg/c101201/12911X4Fb460-2E024.jpg"; 4 5 6 public IntentSer() { 7 super("IntentSer"); 8 // TODO 自動生成的構造函數存根 9 } 10 11 @Override 12 protected void onHandleIntent(Intent intent) { 13 // TODO 自動生成的方法存根 14 15 File file = new File(this.getFilesDir(),"service.png"); 16 try { 17 FileOutputStream outputStream = new FileOutputStream(file); 18 19 InputStream inputStream = new URL(path_url).openStream(); 20 byte[] buffer = new byte[1024]; 21 int len = -1; 22 while((len = inputStream.read(buffer)) != -1){ 23 outputStream.write(buffer, 0, len); 24 } 25 outputStream.close(); 26 inputStream.close(); 27 } catch (FileNotFoundException e) { 28 // TODO 自動生成的 catch 塊 29 e.printStackTrace(); 30 } catch (MalformedURLException e) { 31 // TODO 自動生成的 catch 塊 32 e.printStackTrace(); 33 } catch (IOException e) { 34 // TODO 自動生成的 catch 塊 35 e.printStackTrace(); 36 } 37 38 } 39 40 41 }
在AndroidManifest.xml文件中記得加網絡權限:
<uses-permission android:name="android.permission.INTERNET"/>
由於IntentService繼承於Service,所以要配置環境:
<service android:name=".IntentSer"></service>
運行結果: