自定義網絡請求工具(實現進度條顯示(Android))

在ReactNative使用過程中,我們使用最多的是通過fetch的方法來訪問網絡。但是當用于下載的時候,好像沒有什么好的辦法可以顯示進度條。下面主要介紹的是在安卓原生中自定義網絡請求模塊來請求網絡并且顯示進度。

首先用AndroidStudio打開RN項目下的android文件夾。我們可以看到一個很標準的安卓項目結構。

Paste_Image.png

在項目中我們用已經封裝好的OkHttp工具來實現在原生的網絡訪問。
在gradle下添加

compile 'com.zhy:okhttputils:2.6.2'

在Application對OkhttpUtils進行初始化。

OkHttpClient okHttpClient = new OkHttpClient.Builder()
//                .addInterceptor(new LoggerInterceptor("TAG"))
            .connectTimeout(10000L, TimeUnit.MILLISECONDS)
            .readTimeout(10000L, TimeUnit.MILLISECONDS)
            //其他配置
            .build();
    OkHttpUtils.initClient(okHttpClient);

做好準備工作,接下來就正式進行自定義網絡模塊的封裝。

首先新建MyNetModule繼承ReactContextBaseJavaModule。直接放出代碼
public class MyNetModule  extends ReactContextBaseJavaModule{
    private static final String  REQUSETURL= "URL";
    private static final String  FILEPAHT = "PATH";
    public static  boolean myflag=false;
    public ProgressDialog mDialog,upDialog;




    public MyNetModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }
    @Override
    public String getName() {
        return "MyHttpRequest";
    }
    @ReactMethod
    public void download(final String url, final String filename) {
        mDialog=new ProgressDialog(getCurrentActivity());
        mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mDialog.setTitle("正在下載...");
        mDialog.setCancelable(true);
        mDialog.setCanceledOnTouchOutside(false);// 設置在點擊Dialog外是否取消Dialog進度條
        mDialog.setMax(100);
        mDialog.setButton(DialogInterface.BUTTON_POSITIVE,"取消下載",new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                myflag=true;
                OkHttpUtils.getInstance().cancelTag(getCurrentActivity());
                File file=new File(Environment.getExternalStorageDirectory().getAbsolutePath(),filename);
                file.delete();
            }
        });
        mDialog.show();
        OkHttpUtils//
                .get()//
                .url(url)//
                .tag(getCurrentActivity())
                .build()//
                .execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), filename)//
                {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        mDialog.dismiss();
                        if (myflag) {
                            Toast.makeText(getCurrentActivity(), "下載失敗,用戶取消了下載", Toast.LENGTH_LONG).show();
                        } else {
                            Toast.makeText(getCurrentActivity(), "下載失敗", Toast.LENGTH_LONG).show();
                            Log.v("wt", e.getMessage());
                        }
                        myflag=false;
                    }
                    @Override
                    public void onResponse(File response, int id) {
                        mDialog.dismiss();
                        Toast.makeText(getCurrentActivity(),"下載成功",Toast.LENGTH_LONG).show();
                        Log.v("wt",response.getAbsolutePath());
                    }

                    @Override
                    public void inProgress(float progress, long total, int id) {

                        super.inProgress(progress, total, id);
                        mDialog.setProgress((int) (progress*100));
                        Log.v("wt", String.valueOf(progress));
                    }
                });
    }
    public class MyStringCallback extends StringCallback
    {
        @Override
        public void inProgress(float progress, long total, int id) {
            super.inProgress(progress, total, id);
            Log.v("up", String.valueOf(progress));
            upDialog.setProgress((int) (progress*100));
        }

        @Override
        public void onBefore(Request request, int id)
        {
        }

        @Override
        public void onAfter(int id)
        {
        }

        @Override
        public void onError(Call call, Exception e, int id)
        {
            upDialog.dismiss();
            Log.v("wt",e.getMessage());
        }

        @Override
        public void onResponse(String response, int id)
        {
            upDialog.dismiss();
            Log.e("wt", "onResponse:complete");
          Toast.makeText(getCurrentActivity(),"上傳成功",Toast.LENGTH_LONG).show();
        }

}
    @ReactMethod
    public void upload(String url, final String filename){
        upDialog=new ProgressDialog(getCurrentActivity());
        upDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        upDialog.setTitle("正在上傳...");
        upDialog.setCancelable(true);
        upDialog.setCanceledOnTouchOutside(false);// 設置在點擊Dialog外是否取消Dialog進度條
        upDialog.setMax(100);
        upDialog.setButton(DialogInterface.BUTTON_POSITIVE,"取消上傳",new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                myflag=true;
                Toast.makeText(getCurrentActivity(),"用戶取消上傳",Toast.LENGTH_LONG).show();
                OkHttpUtils.getInstance().cancelTag(getCurrentActivity());

            }
        });
        upDialog.show();
        Map<String, String> headers = new HashMap<>();
        headers.put("application", "octet-stream");
        File file = new File(Environment.getExternalStorageDirectory(), filename);
        Log.v("wt", String.valueOf(file.exists()));
        OkHttpUtils
                .post().addFile("upload",filename,file)
                .url(url)
                .tag(getCurrentActivity())
                .build()
                .execute(new MyStringCallback());
          }
    }

在上面的代碼中。主要利用okhttpUtils實現了上傳和下載的功能以及用ProgressDialog顯示進度。需要注意的是在getName()方法中返回的字符串,在js調用的時候會使用到。

封裝好了MyNetMoudule模塊。我們還需要在ReactPackage中對這個模塊進行注冊。注冊的代碼如下。
public class RCTCommonToolsPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules=new ArrayList<>();
        modules.add( new RCTCommonTools(reactContext));
        modules.add(new MyNetModule(reactContext));
        return modules;
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

上面的代碼主要是寫一個RCTCommonToolsPackage 類繼承于ReactPackage.并在里面實現其三個方法。在createNativeModules方法里面注冊我們自己定義的模塊

注冊完成后,我們還需要在MainApplication里面對我們自定義的package進行注冊。主要代碼如下
 protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
              new RCTCommonToolsPackage(),
                new ReactImageZoom()
      );
    }
  };

到了這里,我們的自定義網絡模塊封裝完畢。
接下來是使用。

'use strict';
var { NativeModules } = require('react-native');
module.exports = NativeModules.MyHttpRequest;
'use strict';

import React, {Component} from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  TouchableOpacity,
  ToastAndroid,
  Alert,
  NativeModules

} from 'react-native';
var url="http://sw.bos.baidu.com/sw-search-sp/software/453ba7195c823/QQPhoneManager_5.6.1.5116.exe";
var fliename="my.apk";
var flie="my.apk";
var uploadurl='http://108.88.0.101:8080/uploadProgress/upload';
import MyHttpRequest from './DwithU.js'
export  default class AwesomeProject extends Component{

HttpDown(){
   MyHttpRequest.download(url,flie)
 }


HttpUp(){
 MyHttpRequest.upload(uploadurl,fliename)
}


  render() {
    return ( 
      <View style = { {flex: 1,justifyContent: 'center',alignItems: 'center' }}>
        <TouchableOpacity onPress = {this.HttpDown }style = {styles.button} >
          <Text > DOWN</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress = {this.HttpUp} style = {styles.button } >
          <Text> UPLOAD </Text> 
        </TouchableOpacity> 
  
      </View>
    );
  }
}

var styles = StyleSheet.create({
  button: {
    width: 180,
    height: 50,
    justifyContent: 'center',
    backgroundColor: '#e2e2e2',
    alignItems: 'center',
    margin: 10,
  }
});

效果圖
Paste_Image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,337評論 25 708
  • 早早睡下,卻怎么也睡不著,索性起來寫寫現在的感受,就像村上春樹說的那樣好讓心靈有個心懷釋然的去處。 現在已經過了冬...
    卿若安閱讀 167評論 0 0
  • 1.LIVE=EVIL,本是同根生。魔鬼屬靈,洞察譏諷詭辯誘惑,無一不通無一不對。愛與上帝爭奪人之靈,也就是搶奪生...
    道伊裘閱讀 592評論 0 2
  • 某型號路由器的緩沖區溢出就能危及成千上萬的WiFi用戶 公共無線網絡的隱私和安全危害有了完美例證,一名以色列黑客展...
    實驗吧閱讀 552評論 0 0
  • 今天,同事小可與米帥在茶水間吵起來了,據同事小八卦說,如果不是汪姐在中間橫著,兩人就動上手了。還沒容我問原因,小八...
    寧青檸閱讀 3,433評論 0 0