android开发,在处理耗时操作的时候,不能再UI(主线程)中处理,有些人为了方便,直接在activity中new 一个新的线程来处理耗时任务,虽然可以达到目的,但是线程不好控制,使用不当可能会导致严重的性能问题。那么如何处理这些耗时的操作呢。
其实android里面的四大组件里面的Service就可以很好的解决这一问题,service和activity差不多,只不过activity是运行在前台,有界面的,而Service是运行在后台的没有界面的。
在activity里面,我们可以通过startService方法打开一个Service,这个Service用来处理比如下载图片,下载文件等等比较耗时的操作。
比如我要下载一个网络文件,并且想要知道下载的进度,通过这个例子,给出几种Service和activity之间通信的方法:
效果图:
方法一:
MainActivity.class
package com.example.wangluo.intentservice;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
public class MainActivity extends Activity implements View.OnClickListener {
private Button button;
private ProgressBar progressBar;
private MyHandler handler;
private ServiceConnection serviceConnection;
private MainService mainService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
handler = new MyHandler(); //初始化handler
//初始化ServiceConnection对象,实现两个回调方法
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//和service连接上时, 会执行此方法
//绑定成功后,会返回一个IBinder对象, 我们通过这个IBinder对象可以得到Service的实例
mainService = ((MainService.MyBind) service).getService();
//将handler对象传递给service,让handler实现service和activity的通信
mainService.setHandler(handler);
}
@Override
public void onServiceDisconnected(ComponentName name) {
//和service断开连接时, 执行此方法
}
};
//绑定service
Intent intent = new Intent("android.intent.action.MainService");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
init();
}
public void init () {
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
//使用Service 暴露出来的方法,下载文件
mainService.downLoadFile();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//Activity销毁的时候, 将service和Activity解绑
unbindService(serviceConnection);
}
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//将handler传递过来的message,赋值在progressBar上,动态显示进度条
progressBar.setProgress(Integer.valueOf(msg.obj.toString()));
//下载完成,解除绑定,提示用户下载完成
if (100 <= Integer.valueOf(msg.obj.toString())) {
//解除绑定
unbindService(serviceConnection);
//Toast下载完成
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}
}
}
}
MainService.class
package com.example.wangluo.intentservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
/**
* Created by wangluo on 2016/3/15.
*/
public class MainService extends Service {
private static final int MAX_FILE_SIZE = 100; //文件大小
private int defaultSize = 0; //从0开始下载文件
private MyThread thread; //下载文件的线程
private Handler handler; //用于Service 和 Activity来通信的对象
//向外暴露接口,用来传入handler对象
public void setHandler (Handler handler) {
this.handler = handler;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyBind();
}
public class MyBind extends Binder {
public MainService getService() {
return MainService.this;
}
}
public void downLoadFile() {
//从0开始下载
defaultSize = 0;
thread = new MyThread(); //new 一个MyThread对象
thread.start(); //开启线程,下载文件
}
class MyThread extends Thread {
@Override
public void run() {
super.run();
//模拟文件下载,每次每秒加10
while (defaultSize < MAX_FILE_SIZE) {
defaultSize += 10;
Message message = new Message(); //message 对象
try {
Thread.sleep(1000); //睡眠1秒
message.obj = defaultSize;
handler.sendMessage(message); //handler传递message
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wangluo.intentservice">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MainService">
<intent-filter>
<action android:name="android.intent.action.MainService" />
</intent-filter>
</service>
</application>
</manifest>
方法一是使用handler实现Service与activity的通信。在activity中绑定Service,拿到Service的实例,然后调用Service的下载文件的方法。
方法二:IntentService 和 activity的通信
MainActivity.java
package com.example.wangluo.broadcastreceiver;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
public class MainActivity extends Activity implements View.OnClickListener {
private Button button;
private ProgressBar progressBar;
private MyReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
receiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.MyReceiver");
//注册广播接收器
registerReceiver(receiver, intentFilter);
init();
}
public void init () {
button.setOnClickListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//注销广播接收器
unregisterReceiver(receiver);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
//开启service,下载文件
Intent intent = new Intent("android.intent.action.MyIntentService");
startService(intent);
break;
}
}
class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int progress = intent.getIntExtra("progress", 0);
progressBar.setProgress(progress);
if (progress >= 100) {
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}
}
}
}
MyIntentService.java
package com.example.wangluo.broadcastreceiver;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
/**
* Created by wangluo on 2016/3/15.
*/
public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
private static final int MAX_FILE_SIZE = 100;
private int defaultSize = 0;
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
downLoadFile();
}
//下载文件的方法
private void downLoadFile() {
Log.e(TAG, "****downLoadFile****");
while (defaultSize < MAX_FILE_SIZE) {
try {
defaultSize += 10;
Thread.sleep(1000);
//发送广播,把进度传过去
Intent intent = new Intent();
intent.setAction("android.intent.action.MyReceiver");
intent.putExtra("progress", defaultSize);
sendBroadcast(intent);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wangluo.broadcastreceiver">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyIntentService">
<intent-filter>
<action android:name="android.intent.action.MyIntentService" />
</intent-filter>
</service>
</application>
</manifest>
方法二使用IntentService与activity通信,使用IntentActivity的好处是,代码更简洁,不用new一个新的线程,因为IntentService运行在一个单独的线程里面,而Service使用运行在应用的主线程里面的。第一种方法不能直接在Service里面执行耗时操作,因为它本身就在主线程里面,而主线程里面不能执行耗时的操作,所以还得新开一个线程去执行耗时的操作,IntentService是不用的。