摘自http://javatechig.com

IntentService

IntentService is a subclass of android.app.Service class. A stated intent service allows to handle long running tasks without effecting the application UI thread. This is not bound to any activity so, it is not getting effected for any change in activity lifecycle. Once IntentService is started, it handles each Intent using a worker thread and stops itself when it runs out of work.

IntentService would be an best solution, If you have an work queue to process. For example, if your application using analytics you will likely to send event name and related parameter to your tracking server for each user generated event. Although each event means a tiny piece of data, creating networking request on each click will result an overhead to your application. Instead, you can use work queue processor design pattern and process the events in a batch.

Limitations

  1. No easy or direct way to interact with user interface directly from IntentService. Later in this example, we will explain to pass result back from IntentService to interface.
  2. With IntentService, there can only be one request processed at any single point of time. If you request for another task, then the new job will wait until the previous one is completed. 
  3. An tasks stated using IntentService cannot be interrupted

 Why do we need IntentService?

Android design guidelines strongly suggests to perform all the long running tasks off the UI thread. For example, if you have to periodically download the largest chunk of data from server, you must use IntentService to avoid ANR. ANR (Application not responding) message often occurs, if your main thread is doing too much of work. In this course of this tutorial, we will learn the below concepts

  1. How to create and use IntentService
  2. How to pass data from activity to service as parameter
  3. How to pass result back to activity
  4. Update activity based on the result

Create an IntentService

In the context of our example, we will create an IntentService to download the data from server. Once download is completed, the response will be sent back to activity. Lets create a new class DownloadService.java and extend it from android.app.IntentService. Now let us override onHandleIntent() method.

When service is started the onHandleIntent() method is called on the worker thread.Unlike Service, IntentService stops itself once it completes its task, so you don’t need to call stopSelf() for stoping the IntentService.

package com.example.msclmacc.intentservice;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;


/**
 * An {@link IntentService} subclass for handling asynchronous task requests in
 * a service on a separate handler thread.
 *


 * TODO: Customize class - update intent actions, extra parameters and static
 * helper methods.
 */
public class DownloadService extends IntentService {
    public static final int STATUS_RUNNING = 0;
    public static final int STATUS_FINISHED = 1;
    public static final int STATUS_ERROR = 2;

    private  static final String TAG = "DownloadService";

    public DownloadService()
    {
        super(DownloadService.class.getName());
    }

    @Override
    protected void onHandleIntent(Intent intent)
    {
        Log.d(TAG,"Service Statred!->onHandleIntent()");

        final ResultReceiver receiver = intent.getParcelableExtra("receiver");
        String url = intent.getStringExtra("url");

        Bundle bundle = new Bundle();

        if(!TextUtils.isEmpty(url))
        {
            receiver.send(STATUS_RUNNING,Bundle.EMPTY);
            try{
                String[] results = downloadData(url);
                if(null != results && results.length > 0 )
                {
                    bundle.putStringArray("result",results);
                    receiver.send(STATUS_FINISHED,bundle);
                }
            }catch (Exception e)
            {
                bundle.putString(Intent.EXTRA_TEXT,e.toString());
                receiver.send(STATUS_ERROR,bundle);
            }
        }
        Log.d(TAG,"Service Stopping!");
        this.stopSelf();
    }

    private String[] downloadData(String requestUrl) throws IOException,DownloadException{
        InputStream inputStream = null;
        HttpURLConnection urlConnection = null;

        URL url = new URL(requestUrl);
        urlConnection = (HttpURLConnection) url.openConnection();

        urlConnection.setRequestProperty("Content-Type","application/json");
        urlConnection.setRequestProperty("Accept","application/json");
        urlConnection.setRequestMethod("GET");

        int statusCode = urlConnection.getResponseCode();

        if(statusCode == 200)
        {
            inputStream = new BufferedInputStream(urlConnection.getInputStream());
            String response = convertInputStreamToString(inputStream);
            String[] results = parseResult(response);
            return results;
        }else
        {
            throw new DownloadException("Failed to fetch data!");
        }
    }

    private String convertInputStreamToString(InputStream inputStream) throws IOException
    {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line = "";
        String result ="";

        while((line = bufferedReader.readLine())!= null)
        {
            result += line;
        }

        if (null != inputStream)
        {
            inputStream.close();
        }
        return result;
    }

    private String[] parseResult(String result)
    {
        String[] blogTitles = null;
        try{
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("posts");

            blogTitles = new String[posts.length()];

            for(int i = 0 ;i< posts.length(); i++)
            {
                JSONObject post = posts.optJSONObject(i);
                String title = post.optString("title");
                blogTitles[i] = title;
            }
        }catch (JSONException e)
        {
            e.printStackTrace();
        }
        return  blogTitles;
    }

    public class DownloadException extends Exception{
        public DownloadException(String message){super(message);}
        public DownloadException(String message,Throwable cause){super(message,cause);}
    }
}

---------------------------------------------

Declaring Service in the Manifest

Like Service, an IntentService also needs an entry in your application manifest. Provide the element entry and declare all your IntentServices you using. Additionally as we are performing operation to download data from internet, we will request for android.permission.INTERNET permission.

<?xml version="1.0" encoding="utf-8"?> xmlns:android="http://schemas.android.com/apk/res/android"    package="com.javatechig.intentserviceexample">         android:name="android.permission.INTERNET" />            android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme">                    android:name=".MyActivity"            android:label="@string/app_name">                             android:name="android.intent.action.MAIN" />                 android:name="android.intent.category.LAUNCHER" />                                                android:name=".DownloadService"            android:exported="false" />    


主界面Activity代码:package com.example.msclmacc.intentservice;
import android.content.Intent;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class MyActivity extends ActionBarActivity implements DownloadResultReceiver.Receiver {
    private ListView listView = null;
    private ArrayAdapter arrayAdapter = null;
    private DownloadResultReceiver mReceiver;

    final String url = "http://javatechig.com/api/get_category_posts/?dev=1&slug=android";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //this.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.activity_my);
        //Initialize listView
        listView = (ListView) findViewById(R.id.listView);

        //Starting Download Service
        mReceiver = new DownloadResultReceiver(new Handler());
        mReceiver.setReceiver(this);

        Intent intent = new Intent(Intent.ACTION_SYNC,null,this,DownloadService.class);
        //Send optional extra to Download IntentService
        intent.putExtra("url",url);
        intent.putExtra("receiver",mReceiver);
        intent.putExtra("requestId",101);

        startService(intent);
    }

    @Override
    public void onReceiverResult(int resultCode, Bundle resultData) {
        switch (resultCode){
            case DownloadService.STATUS_RUNNING:
             //   setProgressBarIndeterminateVisibility(true);
                Toast.makeText(this,"running",Toast.LENGTH_SHORT).show();
                break;
            case DownloadService.STATUS_FINISHED:
              //  setProgressBarIndeterminateVisibility(false);
                Toast.makeText(this,"finished",Toast.LENGTH_SHORT).show();
                String[] results = resultData.getStringArray("result");

                //Update ListView with result
                arrayAdapter = new ArrayAdapter(MyActivity.this, android.R.layout.simple_expandable_list_item_2,results);
                break;
            case DownloadService.STATUS_ERROR:
                String error = resultData.getString(Intent.EXTRA_TEXT);
                Toast.makeText(this,error,Toast.LENGTH_SHORT).show();
                break;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_my, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}


主界面Activity和DownloadService的桥梁---DownloadResultReceiver.java:

package com.example.msclmacc.intentservice;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;

/**
 * Created by MSCLmacC on 8/5/15.
 */
public class DownloadResultReceiver extends ResultReceiver {
    private Receiver mReceiver;
    public void setReceiver(Receiver receiver){mReceiver = receiver;}

    public DownloadResultReceiver(Handler handler) {
        super(handler);
    }

    public interface Receiver{
        public void onReceiverResult(int resultCode,Bundle resultData);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        if(mReceiver != null)
        {
            mReceiver.onReceiverResult(resultCode,resultData);
        }
    }
}

Layout XML code:

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MyActivity">

            android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        >


更多相关文章

  1. android 网络视频代码
  2. android版本更新代码
  3. 系出名门 Android源代码
  4. Android应用程序安装过程源代码分析(3)
  5. android 获取界面上所有控件
  6. Android开发——控件基础(七)ListView组件:示例代码
  7. Ubuntu 13.04 编译环境配置及android 2.3 源代码编译时出现了以
  8. Android应用程序安装过程源代码分析(4)

随机推荐

  1. android TextView设置霓虹灯效果
  2. [Android(安卓)调试/测试] Android(安卓)
  3. Android(安卓)实现书籍翻页效果---番外篇
  4. android调试工具adb命令大全
  5. Android(安卓)Bitmap的加载和Cache
  6. 《Android经验分享》周刊第4期
  7. 关于android中使用new Message的内存泄露
  8. Android(安卓)App Dark Theme(暗黑模式)适
  9. Android(安卓)开发 调用图库选择图片实现
  10. Android(安卓)如何在自定义界面上启用输