Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之在IntentService中執行後台程序

Android之在IntentService中執行後台程序

編輯:關於Android編程

除非我們特別為某個操作指定特定的線程,否則大部分在前台UI界面上的操作任務都執行在一個叫做UI Thread的特殊線程中。這可能存在某些隱患,因為部分在UI界面上的耗時操作可能會影響界面的響應性能。UI界面的性能問題會容易惹惱用戶,甚至可能導致系統ANR錯誤。為了避免這樣的問題,Android Framework提供了幾個類,用來幫助你把那些耗時操作移動到後台線程中執行。那些類中最常用的就是IntentService.

創建IntentService

IntentService為在單一後台線程中執行任務提供了一種直接的實現方式。它可以處理一個耗時的任務並確保不影響到UI的響應性。另外IntentService的執行還不受UI生命周期的影響,以此來確保AsyncTask能夠順利運行。

但是IntentService有下面幾個局限性:

不可以直接和UI做交互。為了把他執行的結果體現在UI上,需要把結果返回給Activity。

工作任務隊列是順序執行的,如果一個任務正在IntentService中執行,此時你再發送一個新的任務請求,這個新的任務會一直等待直到前面一個任務執行完畢才開始執行。

正在執行的任務無法打斷。

雖然有上面那些限制,然而在在大多數情況下,IntentService都是執行簡單後台任務操作的理想選擇。

Step 1: 為你的app創建一個IntentService組件,需要自定義一個新的類,它繼承自IntentService,並重寫onHandleIntent()方法,如下所示:

public class RSSPullService extends IntentService {
    @Override
    protected void onHandleIntent(Intent workIntent) {
        // 這裡可以得到傳進來的intent,就可以獲得intent所攜帶的數據
        String dataString = workIntent.getDataString();
        ...
        // 對獲得的數據進行操作,比如一些耗時的網絡操作
        ...
    }
}

注意:一個普通Service組件的其他回調,例如onCreate()、onStartCommand()會被IntentService自動調用。在IntentService中,要避免重寫那些回調。

Step 2:在Manifest文件中定義IntentService

IntentService需要在manifest文件添加相應的條目如下所示:


    ...

     
     

    


         
        
    ...

注意標簽並沒有包含任何intent filter。因為發送任務給IntentService的Activity需要使用顯式Intent,所以不需要filter。這也意味著只有在同一個app或者其他使用同一個UserID的組件才能夠訪問到這個Service。

至此,你已經有了一個基本的IntentService類,你可以通過構造Intent對象向它發送操作請求。

創建任務請求並發送到IntentService

為了創建一個任務請求並發送到IntentService。需要先創建一個顯式Intent,並將請求數據添加到intent中,然後通過調用 startService() 方法把任務請求數據發送到IntentService。

下面是代碼的示例:

創建一個新的顯式Intent用來啟動IntentService。
/*
 * 創建一個Intent來啟動RSSPullService,把一個鏈接存放進intent中
 */
Intent mServiceIntent = new Intent(getActivity(), RSSPullService.class);
mServiceIntent.setData(Uri.parse(dataUrl));
執行startService()開啟服務
getActivity.startService(mServiceIntent);

注意
可以在Activity或者Fragment的任何位置發送任務請求。例如,如果你先獲取用戶輸入,您可以從響應按鈕單擊或類似手勢的回調方法裡面發送任務請求。

一旦執行了startService(),IntentService在自己本身的onHandleIntent()方法裡面開始執行這個任務,任務結束之後,不需要使用stopService()方法來停止這個服務,因為IntentService會自動停止這個Service

下一步是如何把工作任務的執行結果返回給發送任務的Activity或者Fragment。

利用IntentService將執行任務的結果返回給Activity或者Fragment

下面用一個實例來說明IntentService的一般工作步驟:

(1)在Activity中通過startService啟動service,並傳遞參數。

(2)Service中接收參數,做耗時的處理,處理完畢,發送Broadcat,並把處理結果傳遞出來

(3)Activity中注冊BroadcastReceiver,監聽廣播,更新UI。

Step 1:創建一個IntentService,接收參數

RSSPullService.java

public class RSSPullService extends IntentService {
//
 public static final String BROADCAST_ACTION =
            "com.example.android.threadsample.BROADCAST";


//構造方法必須重寫
 public RSSPullService() {  
        super("RSSPullService");  
    }  

    @Override  
    protected void onHandleIntent(Intent workIntent) {
        //接收參數,做耗時的處理,處理完畢,發送Broadcat  
        //將數據打印出來
       Log.i(TAG,dataString); 
       //接收到數據,做耗時處理
        String result = downloadHtml(dataString);
        Log.i("result",result);

    }  

    ...
}

Step 2:在MainActivity中通過startService啟動IntentService,並傳遞參數

MainActivity.java

public class MainActivity extends AppCompatActivity {
    MyReceiver receiver = new MyReceiver();
    TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    regist();
        bindView();
    }

 private void bindView() {
        mTextView = (TextView)this.findViewById(R.id.textView);
        Button button = (Button)this.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
        //創建一個顯示Intent  
                Intent serviceIntent = new Intent(MainActivity.this,RSSPullService.class);
                //將百度網址傳入Intent
                serviceIntent.setData(Uri.parse("http://www.baidu.com"));
                //啟動服務
                startService(serviceIntent);
            }
        });
    }

    ...

}

Step 3:在MainActivity中注冊廣播,這裡我們利用LocalBroadcastManager來注冊廣播,監聽廣播,

MainActivity.java

private void regist() {

            IntentFilter intentFilter = new IntentFilter(RSSPullService.BROADCAST_ACTION);
        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
        LocalBroadcastManager.getInstance(this).registerReceiver(receiver, intentFilter);
    }

//取消注冊
 protected void onDestroy() {
        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
    }

Step 4:在service中處理耗時操作,並發送Broadcat,並把處理結果傳遞出來

RssPullService.java

public class RSSPullService extends IntentService {

 private static final String TAG = "RSSPullService";

    public static final String EXTENDED_DATA_STATUS =
            "com.example.android.threadsample.STATUS";

    private LocalBroadcastManager mLocalBroadcastManager;

...

 protected void onHandleIntent(Intent intent) {

           ...

    //將耗時操作的結果放進Intent,調用LocalBroadcastManager.sendBroadcast將intent傳遞回去
    Intent localIntent = new Intent(BROADCAST_ACTION);
        localIntent.putExtra(EXTENDED_DATA_STATUS,result);

        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
        mLocalBroadcastManager.sendBroadcast(localIntent);
    }
     ...
     //處理耗時任務的方法
 private String downloadHtml(String dataString) {
        try {
            URL url = new URL(dataString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            InputStream in = conn.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = in.read(buff)) != -1) {
                out.write(buff, 0, len);
            }
            in.close();
            Log.i("html",out.toByteArray().toString());
            return new String(out.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

}

Step 5:在Activity中創建廣播,接收廣播,更新UI

MainActivity.java

 private class MyReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            String data = intent.getStringExtra(RSSPullService.EXTENDED_DATA_STATUS);
            Log.i("test", data);
            mTextView.setText(data);
        }
    }

最後別忘了加上網絡權限:

 

執行結束,效果圖如下:

這裡寫圖片描述

我把主要的幾個類的代碼放上來:

MainActivity.java :

public class MainActivity extends AppCompatActivity {
    MyReceiver receiver = new MyReceiver();
    TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        regist();
        bindView();
    }

    private void regist() {

            IntentFilter intentFilter = new IntentFilter(RSSPullService.BROADCAST_ACTION);
        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
        LocalBroadcastManager.getInstance(this).registerReceiver(receiver, intentFilter);
    }

    private void bindView() {
        mTextView = (TextView)this.findViewById(R.id.textView);
        Button button = (Button)this.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent serviceIntent = new Intent(MainActivity.this,RSSPullService.class);
                serviceIntent.setData(Uri.parse("http://www.baidu.com"));
                startService(serviceIntent);
            }
        });
    }

    private class MyReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            String data = intent.getStringExtra(RSSPullService.EXTENDED_DATA_STATUS);
            Log.i("test", data);
            mTextView.setText(data);
        }
    }

    protected void onDestroy() {
        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
    }
}

RssPullService.java :

public class RSSPullService extends IntentService {
    public static final String BROADCAST_ACTION =
            "com.example.android.threadsample.BROADCAST";

    private static final String TAG = "RSSPullService";

    public static final String EXTENDED_DATA_STATUS =
            "com.example.android.threadsample.STATUS";

    private LocalBroadcastManager mLocalBroadcastManager;

    private ResponseReceiver receiver;

    public RSSPullService() {
        super("RSSPullService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
       String dataString = intent.getDataString();
       Log.i(TAG,dataString);

        String result = downloadHtml(dataString);
        Log.i("result",result);

        Intent localIntent = new Intent(BROADCAST_ACTION);
        localIntent.putExtra(EXTENDED_DATA_STATUS,result);

        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
        mLocalBroadcastManager.sendBroadcast(localIntent);
    }

    private String downloadHtml(String dataString) {
        try {
            URL url = new URL(dataString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            InputStream in = conn.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = in.read(buff)) != -1) {
                out.write(buff, 0, len);
            }
            in.close();
            Log.i("html",out.toByteArray().toString());
            return new String(out.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}

AndroidManifest.xml:



    ...

 
            
                
            
            
    

    
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved