项目架构提炼--状态回调

在开发的工程中,我们经常会遇到,在项目的一些方法执行时,我们想知道,此时的这个方法处于什么阶段,然后将这个阶段返回给前台UI。通俗的举个例子来说,比如我们播放音频,有这个几个过程

  • 开始 -MSG_RECORD_STARTED
  • 暂停-MSG_RECORD_PAUSE
  • 重新开始-MSG_RECORD_RESUME
  • 播放完成-MSG_RECORD_FINISHED

然后,我们执行播放的不同状态中,更新我们上面定义的4个状态,然后回调给Activity,此时Activity就可以进行提示展示。

为什么我们要搞得这么麻烦呢?
比如,我现在实现一个音视频直播。在这个过程中,包含了编解码的过程,音视频频播放的过程以及RTMP推流的过程。我们分别写了3个类,分别是编解码、音视频播放、RTMP推流,然后我们主Activity要知道,这些过程中到底走到哪一步了。此时,我们可以通过状态回调的方式返回给Activity,然后在回调中去处理。

下来看看代码,这样会比较清晰的多

MainActivity.java

package test.com.livetest;

import android.app.Activity;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.github.faucamp.simplertmp.RtmpHandler;
import com.seu.magicfilter.utils.MagicFilterType;

import net.ossrs.yasea.SrsCameraView;
import net.ossrs.yasea.SrsEncodeHandler;
import net.ossrs.yasea.SrsPublisher;
import net.ossrs.yasea.SrsRecordHandler;

import java.io.IOException;
import java.net.SocketException;

/**
 * Created by Sikang on 2017/5/2.
 */

public class CameraActivity extends Activity implements SrsEncodeHandler.SrsEncodeListener, RtmpHandler.RtmpListener, SrsRecordHandler.SrsRecordListener, View.OnClickListener {
    private static final String TAG = "CameraActivity";

  
    private SrsPublisher mPublisher;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_camera);

      ```
      
        mPublisher = new SrsPublisher();
        //编码状态回调
        mPublisher.setEncodeHandler(new SrsEncodeHandler(this));
        //播放状态回调
        mPublisher.setRecordHandler(new SrsRecordHandler(this));
        //rtmp推流状态回调
        mPublisher.setRtmpHandler(new RtmpHandler(this));
        
        ```
    }

   // 这下面就是这三个类回调的状态
    
    @Override
    public void onNetworkWeak() {
        Toast.makeText(getApplicationContext(), "网络型号弱", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onNetworkResume() {

    }

    @Override
    public void onEncodeIllegalArgumentException(IllegalArgumentException e) {
        handleException(e);
    }

    private void handleException(Exception e) {
        try {
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
            mPublisher.stopPublish();
            mPublisher.stopRecord();
            mPublishBtn.setText("开始");
        } catch (Exception e1) {
            //
        }
    }

    @Override
    public void onRtmpConnecting(String msg) {
        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRtmpConnected(String msg) {
        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRtmpVideoStreaming() {

    }

    @Override
    public void onRtmpAudioStreaming() {

    }

    @Override
    public void onRtmpStopped() {
        Toast.makeText(getApplicationContext(), "已停止", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRtmpDisconnected() {
        Toast.makeText(getApplicationContext(), "未连接服务器", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRtmpVideoFpsChanged(double fps) {

    }

    @Override
    public void onRtmpVideoBitrateChanged(double bitrate) {

    }

    @Override
    public void onRtmpAudioBitrateChanged(double bitrate) {

    }

    @Override
    public void onRtmpSocketException(SocketException e) {
        handleException(e);
    }

    @Override
    public void onRtmpIOException(IOException e) {
        handleException(e);
    }

    @Override
    public void onRtmpIllegalArgumentException(IllegalArgumentException e) {
        handleException(e);
    }

    @Override
    public void onRtmpIllegalStateException(IllegalStateException e) {
        handleException(e);
    }

    @Override
    public void onRecordPause() {
        Toast.makeText(getApplicationContext(), "Record paused", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRecordResume() {
        Toast.makeText(getApplicationContext(), "Record resumed", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRecordStarted(String msg) {
        Toast.makeText(getApplicationContext(), "Recording file: " + msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRecordFinished(String msg) {
        Toast.makeText(getApplicationContext(), "MP4 file saved: " + msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRecordIOException(IOException e) {
        handleException(e);
    }

    @Override
    public void onRecordIllegalArgumentException(IllegalArgumentException e) {
        handleException(e);
    }

}

上面的Activity里面,主要就是注册回调,以及实现回调,在各自的方法当中弹出提示

SrsPublisher.java

public void setRtmpHandler(RtmpHandler handler) {
        mFlvMuxer = new SrsFlvMuxer(handler);
           ```
    }

    public void setRecordHandler(SrsRecordHandler handler) {
        mMp4Muxer = new SrsMp4Muxer(handler);
            ```
    }

    public void setEncodeHandler(SrsEncodeHandler handler) {
        mEncoder = new SrsEncoder(handler);
         ```
    }

SrsFlvMuxer、SrsMp4Muxer、SrsEncoder这三个类是真正执行的类,我们在里面的不同方法中调用即可

比如说 mMp4Muxer .java

构造方法将SrsRecordHandler 传进来

 public SrsMp4Muxer(SrsRecordHandler handler) {
        mHandler = handler;
    }
    

然后在,在真正执行的方法中,去更新状态

    /**
     * pause recording.
     */
    public void pause() {
        if (bRecording) {
            bPaused = true;
            mHandler.notifyRecordPause();
        }
    }

    /**
     * resume recording.
     */
    public void resume() {
        if (bRecording) {
            bPaused = false;
            needToFindKeyFrame = true;
            mHandler.notifyRecordResume();
        }
    }

    /**
     * finish recording.
     */
    public void stop() {
        bRecording = false;
        bPaused = false;
        needToFindKeyFrame = true;
        aacSpecConfig = false;
        frameCache.clear();

        if (worker != null) {
            try {
                worker.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
                worker.interrupt();
            }
            worker = null;

            finishMovie();
            mHandler.notifyRecordFinished(mRecFile.getPath());
        }
        Log.i(TAG, "SrsMp4Muxer closed");
    }

上面的 mHandler.notifyRecordResume()等方法是什么呢?我们在跟进去看看SrsRecordHandler类看看
SrsRecordHandler.java

package net.ossrs.yasea;

import android.os.Handler;
import android.os.Message;

import java.io.IOException;
import java.lang.ref.WeakReference;

/**
 * Created by leo.ma on 2016/11/4.
 */

public class SrsRecordHandler extends Handler {

    private static final int MSG_RECORD_PAUSE = 0;
    private static final int MSG_RECORD_RESUME = 1;
    private static final int MSG_RECORD_STARTED = 2;
    private static final int MSG_RECORD_FINISHED = 3;

    private static final int MSG_RECORD_ILLEGEL_ARGUMENT_EXCEPTION = 4;
    private static final int MSG_RECORD_IO_EXCEPTION = 5;

    private WeakReference mWeakListener;

    public SrsRecordHandler(SrsRecordListener listener) {
        mWeakListener = new WeakReference<>(listener);
    }

    public void notifyRecordPause() {
        sendEmptyMessage(MSG_RECORD_PAUSE);
    }

    public void notifyRecordResume() {
        sendEmptyMessage(MSG_RECORD_RESUME);
    }

    public void notifyRecordStarted(String msg) {
        obtainMessage(MSG_RECORD_STARTED, msg).sendToTarget();
    }

    public void notifyRecordFinished(String msg) {
        obtainMessage(MSG_RECORD_FINISHED, msg).sendToTarget();
    }

    public void notifyRecordIllegalArgumentException(IllegalArgumentException e) {
        obtainMessage(MSG_RECORD_ILLEGEL_ARGUMENT_EXCEPTION, e).sendToTarget();
    }

    public void notifyRecordIOException(IOException e) {
        obtainMessage(MSG_RECORD_IO_EXCEPTION, e).sendToTarget();
    }

    @Override  // runs on UI thread
    public void handleMessage(Message msg) {
        SrsRecordListener listener = mWeakListener.get();
        if (listener == null) {
            return;
        }

        switch (msg.what) {
            case MSG_RECORD_PAUSE:
                listener.onRecordPause();
                break;
            case MSG_RECORD_RESUME:
                listener.onRecordResume();
                break;
            case MSG_RECORD_STARTED:
                listener.onRecordStarted((String) msg.obj);
                break;
            case MSG_RECORD_FINISHED:
                listener.onRecordFinished((String) msg.obj);
                break;
            case MSG_RECORD_ILLEGEL_ARGUMENT_EXCEPTION:
                listener.onRecordIllegalArgumentException((IllegalArgumentException) msg.obj);
                break;
            case MSG_RECORD_IO_EXCEPTION:
                listener.onRecordIOException((IOException) msg.obj);
                break;
            default:
                throw new RuntimeException("unknown msg " + msg.what);
        }
    }
    
    public interface SrsRecordListener {

        void onRecordPause();

        void onRecordResume();

        void onRecordStarted(String msg);

        void onRecordFinished(String msg);

        void onRecordIllegalArgumentException(IllegalArgumentException e);

        void onRecordIOException(IOException e);
    }
}

这个类是重点 ,在这个类里面,我们通过真正执行方法的调用以后,向外层发送handler,不同的更新就有不同类型的handler,然后在通过接口回调,返回个主Activity。

你可能感兴趣的:(Android)