Activityとserviceは互いに情報を伝達する

22241 ワード

Activityとserviceは互いに情報を伝達する
ビジネスではサービスでバックグラウンド操作を実行することが多く、一般的にactivityとバインドされ、activityはサービスを制御できますが、ビジネスではactivityとサービスの情報交流は相互に行われます.解決策はいくつかあり、ここではインタフェースを用いたスキームがメッセージを相互接続する目的を達成することを説明する.
まずactivityはbinderによってサービスをバインドし、次にバインドbinderにサービスインスタンスを渡し、activityでサービスインスタンスを取得し、インタフェースをバインドします.たとえば、サービスでネットワークインタフェースを絶えず要求する場合は、戻り値をactivityに伝える必要がありますが、activityはこのネットワーク要求をオンまたは一時停止する必要があります.以下に簡単なビジネスコードを示します.
1.サービスを作成し、そこに共通のクラスを作成し、Binderを継承します.このクラスのオブジェクトはactivityがサービスをバインドした後に取得できます.2.クラスにメソッドを記述し、戻り値がサービスのタイプであり、activityがサービスのインスタンスオブジェクトを取得できるようにします.                  3.最後にサービスにインタフェースを記述し、activityで傍受し、サービスにactivityのように返す必要がある値がある場合に返す.
Serviceコード:workメソッドでMyServiceオブジェクトを返し、workThreakでactivityにデータを渡す必要があります.
startWorkおよびstopWorkメソッドは、activityがスレッド内の作業の停止および開始を開始および停止するために使用します.
public class MyService extends Service {

    private Work work;
    //        ,     
    private WeakReference myService = new WeakReference<>(MyService.this);
    private static final String TAG = "MyService";

    public MyService() {
        threadFlag = true;
        workThread.start();
    }

    private Work getWork() {
        if (work == null) {
            work = new Work();
        }
        return work;
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return getWork();
    }

    @Override
    public void onDestroy() {
        threadFlag = false;
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }

    public class Work extends Binder {
        public void startWork() {
            //    
            flag = true;
        }

        public void stopWork() {
            //    
            flag = false;
        }

        public MyService getMyService() {
            return myService.get();
        }
    }

    //     
    private boolean flag = true;

    //       
    private boolean threadFlag = true;

    private int i = 0;

    //        
    private Thread workThread = new Thread() {
        @Override
        public void run() {
            while (threadFlag) {
                if (flag) {
                    //             handler      
                    i++;
                    SystemClock.sleep(2000);
                    Message message = handler.obtainMessage();
                    message.obj = i;
                    message.what = 1;
                    handler.sendMessage(message);
                }
            }
        }
    };
    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    int message = (int) msg.obj;
                    //        
                    if (callBacks != null && callBacks.size() > 0) {
                        for (CallBack callBack :
                                callBacks) {
                            callBack.postMessage(message);
                        }
                    }
            }
            super.handleMessage(msg);
        }
    };

    /**
     *    activity                activity            list   
     */

    public interface CallBack {
        void postMessage(int message);
    }

    private List callBacks = new LinkedList<>();

    //    
    public void registerCallBack(CallBack callBack) {
        if (callBacks != null) {
            callBacks.add(callBack);
        }
    }

    /**
     *      false    
     *
     * @param callBack
     * @return
     */
    public boolean unRegisterCallBack(CallBack callBack) {
        if (callBacks != null && callBacks.contains(callBack)) {
            return callBacks.remove(callBack);
        }
        return false;
    }
}

Activityコード:サービス接続でMyserviceのWorkクラスを取得し、getMyserviceを呼び出して現在バインドされているサービスのインスタンスを取得し、リスニングを登録することで、サービスで実行された結果をactivityに戻すことができます.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private boolean bindService;
    private MyService.Work work;
    private MyService myService;
    private TextView tv_text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_start).setOnClickListener(this);
        findViewById(R.id.btn_stop).setOnClickListener(this);
        tv_text = findViewById(R.id.tv_text);
        bindService();
    }

    //  service
    private void bindService() {
        Intent intent = new Intent(this, MyService.class);
        startService(intent);
        bindService = bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection serviceConnection = new ServiceConnection() {


        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //    binder      MyService.Work
            work = (MyService.Work) iBinder;
            myService = work.getMyService();
            myService.registerCallBack(callBack);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            if (myService != null) {
                myService.unRegisterCallBack(callBack);
            }
        }
    };

    private MyService.CallBack callBack = new MyService.CallBack() {
        @Override
        public void postMessage(int message) {
            tv_text.setText("service do result-----> " + message);
        }
    };

    public void unBindService() {
        if (bindService && serviceConnection != null) {
            unbindService(serviceConnection);
        }
    }

    @Override
    protected void onDestroy() {
        unBindService();
        super.onDestroy();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_start:
                if (work!=null){
                    work.startWork();
                }
                break;
            case R.id.btn_stop:
                if (work!=null){
                    work.stopWork();
                }
                break;
        }
    }
}

githubアドレス:クリックしてリンクを開く
実行するgif図:クリックしてリンクを開く