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是不用的。