react-native android热更新详解----增加进度条(4)

1.最新研究react-native android热更新组件react-native-pushy,发现官方例子只有更新成功或失败的回调,没有更新进度回调,所以自己捣鼓一个更新进度获取和显示。

          下面是热更新android源码,只有 public void onDownloadCompleted()和public void onDownloadFailed(Throwable error)这两个回调方法。

    @ReactMethod
    public void downloadUpdate(ReadableMap options, final Promise promise){
        String url = options.getString("updateUrl");
        String hash = options.getString("hashName");
        updateContext.downloadFile(url, hash, new UpdateContext.DownloadFileListener() {
            @Override
            public void onDownloadCompleted() {
                promise.resolve(null);//成功回调
            }
            @Override
            public void onDownloadFailed(Throwable error) {
                promise.reject(error);//失败回调
            }
        });
    }

2.因为没有进度回调,怎么办?我想出两个方案:

         方案一:回调接口增加一个进度回调方法

    public interface DownloadFileListener {
        void onDownloadCompleted();
        void onDownloadProgress();//进度回调
        void onDownloadFailed(Throwable error);
    }

         方案二:获取下载进度,使用事件方式发送到js这边,通过监听更新进度页面。

3.方案一实现:

         downloadFile这个下载方法使用Hander Message  方式发下载进度发送到回调接口 void onDownloadProgress()。onDownloadProgress是一个异步方法,Hander Message也是异步的,感觉不太行。可能有其它方法但是太啰嗦了,所以放弃调。

4.方案二实现:

          继续研究官方源码,发现下载类是这个

class DownloadTask extends AsyncTask 

关键在付类AsyncTask,AsyncTask是一个抽象类

public abstract class AsyncTask 

继续深入研究AsyncTask,AsyncTask有以下重要方法:

 protected abstract Result doInBackground(Params... var1);

    protected void onPreExecute() {
        throw new RuntimeException("Stub!");
    }

    protected void onPostExecute(Result result) {
        throw new RuntimeException("Stub!");
    }

    protected void onProgressUpdate(Progress... values) {
        throw new RuntimeException("Stub!");
    }

    protected void onCancelled(Result result) {
        throw new RuntimeException("Stub!");
    }

    protected void onCancelled() {
        throw new RuntimeException("Stub!");
    }
  protected final void publishProgress(Progress... values) {
        throw new RuntimeException("Stub!");
    }

找到了:这两个方法是我们需要的

protected void onProgressUpdate(Progress... values)   下载进度回调

protected final void publishProgress(Progress... values)  发布一个进度信息

5.在DownloadTask.java  ,DownloadTask 类代码修改。

        5.1覆写protected void onProgressUpdate(Progress... values) 这个方法

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        System.out.println("Progress values" +values[0]);//打印进度
        WritableMap params = Arguments.createMap();
        params.putString("progress", values[0].toString()); //包装数据
        sendEvent("progress", params);//发送一个事件,把数据发出去

    }

5.2 private void downloadFile(String url, File writePath) 代码修改

关键代码: 、

           int pro=(int)((totalRead*1.0 / (contentLength*1.0))*100);//进度转换成百分比
            publishProgress(pro);//发布进度到onProgressUpdate

以下是downloadFile整个方法源码:

 private void downloadFile(String url, File writePath) throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        Response response = client.newCall(request).execute();
        if (response.code() > 299) {
            throw new Error("Server return code " + response.code());
        }
        ResponseBody body = response.body();
        long contentLength = body.contentLength();
        BufferedSource source = body.source();

        if (writePath.exists()) {
            writePath.delete();
        }

        BufferedSink sink = Okio.buffer(Okio.sink(writePath));

        if (UpdateContext.DEBUG) {
            Log.d("RNUpdate", "Downloading " + url);
        }

        long bytesRead = 0;
        long totalRead = 0;
        while ((bytesRead = source.read(sink.buffer(), DOWNLOAD_CHUNK_SIZE)) != -1) {
            totalRead += bytesRead;
            if (UpdateContext.DEBUG) {
                Log.d("RNUpdate", "Progress " + totalRead + "/" + contentLength);
            }
           System.out.println("Progress " + totalRead + "/" + contentLength);
            int pro=(int)((totalRead*1.0 / (contentLength*1.0))*100);//进度转换成百分比
            publishProgress(pro);//发布进度到onProgressUpdate
        }
        if (totalRead != contentLength) {
            throw new Error("Unexpected eof while reading ppk");
        }
        sink.writeAll(source);
        sink.close();

        if (UpdateContext.DEBUG) {
            Log.d("RNUpdate", "Download finished");
        }
    }

5.3UpdateModule.java 这个类加个发送事件方法

关键代码:
public static ReactApplicationContext mContext;//定义一个静态 ReactApplicationContext
public UpdateModule(ReactApplicationContext reactContext, UpdateContext updateContext) {
    super(reactContext);
    this.updateContext = updateContext;
    mContext=reactContext;//reactContext赋值mContext
}

//增加静态事件发送

/* 发送事件 */
public static void sendEvent(String eventName,  WritableMap params) {
    ((ReactContext) mContext).getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName,
            params);
}

5.4使用事件发送

5.4.1 DownloadTask.java  导包  

import static cn.reactnative.modules.update.UpdateModule.sendEvent;

5.4.2发送事件

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        System.out.println("Progress values" +values[0]);//打印进度
        WritableMap params = Arguments.createMap();
        params.putString("progress", values[0].toString()); //包装数据
        sendEvent("progress", params);//发送一个事件,把数据发出去

    }

6.js代码接收,android java代码发送的进度数据。

6.1导入DeviceEventEmitter

6.2监听事件

  componentDidMount() {

    DeviceEventEmitter.addListener('progress', (pro) => {

   console.log('Progress' + pro.progress)

      this.setState({ progress: pro.progress })

    });

  }

6.3显示代码

 

          更新进度{this.state.progress}

        

7.git完整源码 https://github.com/nfq6612/hottest

你可能感兴趣的:(react-native,reactnative热更新,热更新进度)