第一行代码读书笔记
服务
- 安卓实现后台运行的解决方案
- 不需要和用户交互并要求长期运行的任务
- 依赖于创建服务时所在的应用程序进程
- 在服务内部主动创建子线程,防止主线程被阻塞
多线程编程
基本用法
- 定义线程
class MyThread extends Thread { @Override public void run() { // 处理具体逻辑 } }
- 启动线程
new MyThread().start();
- 使用继承的方式耦合性高,一般使用
Runnable
接口实现来定义线程class MyThread implemments Runnable { @Override public void run() { // 处理具体逻辑 } }
- 使用
Runnable
接口时启动线程MyThread myThread = new MyThread(); new Thread(myThread).start();
- 匿名类实现更为常见
new Thread(new Runnable() { @Override public void run() { // 处理具体逻辑 } }
在子线程中更新UI
- 异步消息处理
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int UPDATE_TEXT = 1;
private TextView text;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
// 在这里可以进行UI操作
text.setText("Nice to meet you");
break;
default:
break;
}
}
}
...
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.change_text:
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
})
}
}
}
解析异步消息处理机制
- Message
- 进程之间传递的消息,可以在内部携带少量的信息,用于不同线程之间交换数据
- Handler
- 用于发送和处理消息
sendMessage()
handleMessage()
- MessageQueue
- 用于存放所有通过Handler发送的消息
- 一直存在消息队列中等待被处理
- 每个线程中只有一个
- Looper
- MessageQueue的管家,无限循环,每当发现MessageQueue中存在消息就会取出并传递到
handleMessage()
- 每个线程中只有一个
- MessageQueue的管家,无限循环,每当发现MessageQueue中存在消息就会取出并传递到
runOnUiThread()
:异步消息处理机制的接口封装
使用AsyncTask
- 抽象类,继承的时候可以指定3个泛型参数
Params
:执行AsyncTask时需要传入的参数,可用于后台任务中使用Progress
:进度单位(后台任务执行时,如需要在界面上显示当前的进度)Result
:返回值类型(当任务执行完毕后,如需要对结果进行返回)
- 经常需要重写的方法
onPreExecute()
- 后台任务开始前调用
- 用于进行界面上的初始化操作
doInBackground(Params...)
- 处理所有的耗时任务
- 完成后可以通过return将任务的执行结果返回
- 如果AsynTask的第三个泛型参数指定的是Void,就可以不返回任务结果
- 不能进行UI操作,如果需要,调用
publishProgress(Progress...)
来完成
onProgressUpdate(Progress...)
- 当在后台任务中调用了
publishProgress(Progress...)
后调用 - 携带的参数是在后台任务中传递过来的
- 可以进行UI操作
- 当在后台任务中调用了
onPostExecute(Result)
- 当后台任务执行完毕并通过return语句进行返回时调用
- 返回的数据作为参数
- 可以进行UI操作
- E.g.
class DownloadTask extends AsyncTask<Void, Integer, Boolean> { @Override protected void onPreExecute() { ProgressDialog.show(); } @Override protected Boolean doInBackground(Void... params) { try { while (true) { int downloadPercent = doDownload(); publishProgress(downloadPercent); if (downloadPercent >= 100) { break; } } } catch (Exception e) { return false; } return true; } @Override protected void onProgressUpdate(Integer... values) { progressDialog.setMessage("Download " + values[0] + "%"); } @Override protected void onPostExecute(Boolean result) { progressDialog.dismiss(); if (result) { Toast.makeText(context, "Download succeeded", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, ""Download failed", Toast.LENGTH_SHORT).show(); } } }
- 启动任务
new DownloadTask().execute()
服务的基本用法
定义一个服务
- New->Service->Service
- Exported:是否运行除了当前程序的其他程序访问这个服务
- Enabled:是否启用这个服务
public class Myservice extends Service() {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommond(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
- onStartCommand():服务一启动立刻执行
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
</service>
启动和停止服务
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_service:
Intent startIntent new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.stop_service:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
活动和服务进行通讯
-
onBind()
-
MyService中:
public class MyService extends Service { private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends 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; } }
-
MainActivity中
private MyService.DownloadBinder downloadBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { downloadBinder = (MyService.DownloadBinder) service; downloadBinder.startDownload(); downloadBinder.getProgress(); } }
@Override public void onClick(View v) { switch (v.getId()) { ... case R.id.bind_service: Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTOCEATE); break; case R.id.unbind_service: unbindService(connection); break; default: break; } }
服务的生命周期
- onCreate()(如果活动未创建)-> onStartCommand() -> 运行直到StopService()或stopSelf()被调用
- 调用Contextd bindService获取一个服务的持久链接
- 只要被启动或者被绑定,就会一直处于运行状态,同时调用stopService()和unbindService(),onDestroy()才能被执行
其他技巧
前台服务
- 避免你由于系统内存不足被回收
- 一直有一个正在运行的图标在系统的状态栏显示
- MyService的onCreate()中:
Intent intent = new Intent(this, MainActivity.class); PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0); Notification notification = new NotificationCompat.Builder(this) .setContentTitle("This is content title") .setContentText("This is content text") .setWhen(System.currentTimeMillis()) .setSmallIcon(R.mipmap.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .setContentIntent(pi) .build(); startForeground(1, notification);
IntentService
public MyIntentService extentds IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d("MyIntentService", "Thread id is " + Thread.currentThread().getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}