android开发,在处理耗时操作的时候,不能再UI(主线程)中处理,有些人为了方便,直接在activity中new 一个新的线程来处理耗时任务,虽然可以达到目的,但是线程不好控制,使用不当可能会导致严重的性能问题。那么如何处理这些耗时的操作呢。

其实android里面的四大组件里面的Service就可以很好的解决这一问题,service和activity差不多,只不过activity是运行在前台,有界面的,而Service是运行在后台的没有界面的。

在activity里面,我们可以通过startService方法打开一个Service,这个Service用来处理比如下载图片,下载文件等等比较耗时的操作。

比如我要下载一个网络文件,并且想要知道下载的进度,通过这个例子,给出几种Service和activity之间通信的方法:


效果图:

Android 停止 前台服务 android前台service_ide

Android 停止 前台服务 android前台service_Android 停止 前台服务_02

Android 停止 前台服务 android前台service_线程_03



方法一:

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