$《第一行代码:Android》读书笔记——第9章 服务
class MyThread extends Thread{
public void run( ){
//执行耗时操作
}
}
new MyThread( ).start( );
(2)实现Runnable接口:
class MyRunnable implements Runnable{
public void run( ){
//执行耗时操作
}
}
new Thread(new MyRunnable).start( );
(3)使用匿名类:
new Thread(new Runnable( ){
public void run( ){
//执行耗时操作
}
}).start( );
2、Android不允许在子线程中更新UI,只能在主线程中更新。
private Handler handler = new Handler( ){
public void handleMessage(Message msg){
switch(msg.what){ //msg的what字段是一个标志字段,整型
case xxx:
//在这里可以进行UI操作
textView.setText("Change text succeed!") //改变textView的字符
break;
default:
break;
}
}
}
(2)在子线程中需要进行UI操作时(如按钮点击事件中),创建一个Message对象,并通过Handler对象的sendMessage方法将该消息发送出去,比如:
public static final int UPDATE_TEXT = 1; //修改UI的标志值
......
@Override
public void onClick(View v){
switch(v.getId( )){
case R.id.chage_text_btn:
new Thread(new Runnable( ){
@Override
public void run( ){
Message msg = new Message( );
msg.what = UPDATE_TEXT ;
handler.sendMessage(msg);
}
}).start( );
break; default:
break;
}
}

class MyAsyncTask extends AsyncTask<Params, Progress, Result>
(五)Service
1、定义Service:
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService", "onCreate executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyService", "onDestroy executed");
}
}
2、Service类中有一个抽象方法onBind,还有三个常用方法:
<application
... >
<service android:name=".MyService" >
</service>
...
</application>
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
(2)停止:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
5、Activity和Service通信:
(1)在Service中安插内线Binder,并在onBind方法中发送这个内线:
public class MyService extends Service {
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder { //自定义Binder,模拟下载功能
public void startDownload() {
Log.d("MyService", "startDownload executed");
}
public int getProgress() {
Log.d("MyService", "getProgress executed");
return 0;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
... //其他方法
}
(2)在Activity中创建内线及ServiceConnection,其中的onServiceConnected方法即可接收内线IBinder并通过向下转型获取Binder:
...
private MyService.DownloadBinder downloadBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (MyService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProgress();
} @Override
public void onServiceDisconnected(ComponentName name) { };
};
...
(3)在合适的时候(如按钮的点击事件等)绑定Activity与Service:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE); //BIND_AUTO_CREATE指当绑定后,自动创建Service
(4)解除绑定:
if(connection != null){
unbindService(connection);
}
startService( )
onCreate( )
onStartCommand( )
onDestory( )
bindService( )
unbindService( )
stopService( )
stopSelf( ) //在Service中任何地方都可以用这个方法结束服务本身
onBind( )
(3)如果startService( )和bindService( )都调用了,那么必须同时满足unbindService( )和stopService( )都被调用才会执行onDestory( )方法。
7、前台Service:在系统状态栏中一直显示的可见Service,只需在Service的onCreate方法中添加如下代码即可(其实是通知的用法):
@Override
public void onCreate() {
super.onCreate();
...
Notification notification = new Notification(R.drawable.ic_launcher,
"Notification comes", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(this, "This is title",
"This is content", pendingIntent);
startForeground(1, notification);
}
8、IntentService:
服务的代码默认都是在主线程中的,如果直接在服务里去处理一些耗时逻辑,就很容易出现ANR(Application Not Responding)的情况。这时就可以方便的使用已经把多线程封装好的IntentService类:
public class MyIntentService extends IntentService {
public MyIntentService() { //需要一个无参的构造方法,调用父类的有参构造方法
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) { //这个方法默认在子线程中运行
// 打印当前线程ID
Log.d("MyIntentService", "Thread id is "
+ Thread.currentThread().getId());
// 在这里已经是在子线程中运行了,可以执行一些耗时操作,但不能执行UI操作
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}
IntentService在任务处理完后,会自动调用onDestory方法,不用再去人工调用unbindService或stopService方法。其他用法和普通Service一样。
(六)Service最佳实践:后台定时任务
import java.util.Date; import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log; public class LongRunningService extends Service { @Override
public IBinder onBind(Intent intent) {
return null;
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
//创建子线程打印当前时间,模拟定时任务
new Thread(new Runnable() {
@Override
public void run() {
Log.d("LongRunningService",
"executed at " + new Date().toString());
}
}).start();
//1.创建AlarmManager
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
int aMinute = 60 * 1000; // 一分钟的毫秒数
long triggerAtTime = SystemClock.elapsedRealtime() + aMinute;
//2.创建跳到广播接收器的Intent
Intent i = new Intent(this, AlarmReceiver.class);
//3.创建PendingIntent
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
//4.使用AlarmManager的set方法
//第一个参数:指定工作类型,有四种:ELAPSED_REALTIME_WAKEUP表示定时任务触发时间从
//系统开机算起,会唤醒CPU;ELAPSED_REALTIME,同ELAPSED_REALTIME_WAKEUP,但不会唤醒CPU;
//RTC表示从1970-1-1 00:00算起,不会唤醒CPU,RTC_WAKEUP同RTC,但会唤醒CPU。
//注:唤醒CPU和唤醒屏幕是不同的概念。
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi); return super.onStartCommand(intent, flags, startId);
}
}
3、创建AlarmReceiver类:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; public class AlarmReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, LongRunningService.class);
context.startService(i); //反过来再启动服务,交替循环进行下去
}
}
4、在活动中启动服务:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Intent i = new Intent(this, LongRunningService.class);
startService(i);
}
}
5、在AndroidManifest.xml中注册服务和广播接收器。
【本章结束】
随机推荐
- 设计模式中类的关系之聚合关系(Aggregation)
聚合关系是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系,此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享.比如计算机与 ...
- Win10:如何修改双网卡的优先级?
很多使用双网卡的IT之家网友可能遇到一种情况,比如笔记本电脑在插上网线后还是用WiFi,得手动关闭无线连接才能转换到有线连接.如何才能调整合适的网络优先级呢?一般来说,有两种方法比较常用. 一.调整网 ...
- 通知:spark meetup 第六次会议在北京举行
通知: Spark北京Meetup第六次活动(机器学习专题) 将于北京时间3月21日 下午14:00-18:00 在微软亚太研发集团总部大厦1号楼举行,主题包括: Julien Pierre Pr ...
- Struts2 结果和结果类型
正如前面提到的,<results>标签在Struts2的MVC框架的视图中所扮演的角色.动作是负责执行业务逻辑.执行业务逻辑后,接下来的步骤是使用<results>标签显示的视 ...
- java中Statement详细用法。
1.创建 Statement 对象 建立了到特定数据库的连接之后,就可用该连接发送 SQL 语句.Statement 对象用 Connection 的方法createStatement 创建,如下列代 ...
- python django -6 常用的第三方包或工具
常用的第三方包或工具 富文本编辑器 缓存 全文检索 celery 布署 富文本编辑器 借助富文本编辑器,管理员能够编辑出来一个包含html的页面,从而页面的显示效果,可以由管理员定义,而不用完全依赖于 ...
- poj 2117(割点的应用)
题目链接:http://poj.org/problem?id=2117 思路:题目的意思是要求对于给定的无向图,删除某个顶点后,求最大的连通分量数.显然我们只有删掉割点后,连通分支数才会增加,因此我们 ...
- 部署网站时的错误“one of its dependencies.试图加载格式不正确的程序。”解决方案。
Sever Error in '/' Application.Could not load file or assembly 'SresBase' or one of its dependencies ...
- [Docker]学习笔记--简单介绍
学习docker已经有一段时间了,一直没有静下心来好好总结一下. 最近用docker搭了一整套Gitlab的持续集成环境.(会在下一篇中详细的讲解具体步骤,敬请期待) 感觉是时候写点东西和大家一起分享 ...
- T-SQL 合并多行数据显示到一行
思路: 自连接,使用For XML Path('')和STUFF函数 SELECT * FROM STUDENT Name Team------------- ...