Android之在IntentService中执行后台程序
来源:互联网 发布:可靠性软件招标2016 编辑:程序博客网 时间:2024/06/05 09:45
说明——
关于四大组件之一的Service,对它的基本用法不熟悉的可以去看看这个博客!
Service完全解析
除非我们特别为某个操作指定特定的线程,否则大部分在前台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文件添加相应的条目如下所示:
<application android:icon="@drawable/icon" android:label="@string/app_name"> ... <activity android:name=".MainActivity"> </activity> <!-- android:exported 被设置为"false", 保证服务只会在这个App内部运行 --><service android:name=".RSSPullService" android:exported="false"> <!-- 可以为服务添加相应的响应方式和过滤 <intent-filter > <action android:name="com.example.android.threadsample.BROADCAST"/> </intent-filter> --> </service> ...<application/>
注意<service>
标签并没有包含任何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); } }
最后别忘了加上网络权限:
<uses-permission android:name="android.permission.INTERNET" />
执行结束,效果图如下:
我把主要的几个类的代码放上来:
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:
<application> ... <service android:name=".RSSPullService" android:exported="false"> <intent-filter > <action android:name="com.example.android.threadsample.BROADCAST"/> </intent-filter> </service> </application> <uses-permission android:name="android.permission.INTERNET" />
- Android之在IntentService中执行后台程序
- android中service之intentService
- Android中使用IntentService执行后台任务
- Android中使用IntentService执行后台任务
- Android中Services之异步IntentService
- Android中Services之异步IntentService
- Android中Services之异步IntentService
- Android中Services之异步IntentService
- Android中Services之异步IntentService
- Android中Services之异步IntentService
- Android中Services之异步IntentService
- Android之IntentService
- android之IntentService
- Android 之IntentService学习
- android之intentservice
- Android开发之IntentService
- Android之IntentService
- android之IntentService
- 判断两个区间范围是否重复
- Linux命令行模式修改语言&菱形乱码解决方法
- LayerAnchorPoint
- 3-3 构造函数的调用(高级)
- Fragment基本使用(二)——动态加载
- Android之在IntentService中执行后台程序
- [kuangbin带你飞]专题一 简单搜索 I FZU 2150
- 第三周 项目 4 顺序表的应用 (1)(补)
- deBug日志_关于在多个fragment中又嵌套多个fragment导致控件显示错乱与不知名bug
- Java集合框架之Collection实例解析
- 内存溢出、内存泄露、内存越界、缓冲区溢出、栈溢出
- 五款最佳Linux下载管理器推荐
- 数据结构队列之javascript实现
- MySQL --索引操作 与 优化