在ReactNative使用過程中,我們使用最多的是通過fetch的方法來訪問網(wǎng)絡(luò)。但是當(dāng)用于下載的時(shí)候,好像沒有什么好的辦法可以顯示進(jìn)度條。下面主要介紹的是在安卓原生中自定義網(wǎng)絡(luò)請(qǐng)求模塊來請(qǐng)求網(wǎng)絡(luò)并且顯示進(jìn)度。
首先用AndroidStudio打開RN項(xiàng)目下的android文件夾。我們可以看到一個(gè)很標(biāo)準(zhǔn)的安卓項(xiàng)目結(jié)構(gòu)。

Paste_Image.png
在項(xiàng)目中我們用已經(jīng)封裝好的OkHttp工具來實(shí)現(xiàn)在原生的網(wǎng)絡(luò)訪問。
在gradle下添加
compile 'com.zhy:okhttputils:2.6.2'
在Application對(duì)OkhttpUtils進(jìn)行初始化。
OkHttpClient okHttpClient = new OkHttpClient.Builder()
// .addInterceptor(new LoggerInterceptor("TAG"))
.connectTimeout(10000L, TimeUnit.MILLISECONDS)
.readTimeout(10000L, TimeUnit.MILLISECONDS)
//其他配置
.build();
OkHttpUtils.initClient(okHttpClient);
做好準(zhǔn)備工作,接下來就正式進(jìn)行自定義網(wǎng)絡(luò)模塊的封裝。
首先新建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);// 設(shè)置在點(diǎn)擊Dialog外是否取消Dialog進(jìn)度條
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);// 設(shè)置在點(diǎn)擊Dialog外是否取消Dialog進(jìn)度條
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實(shí)現(xiàn)了上傳和下載的功能以及用ProgressDialog顯示進(jìn)度。需要注意的是在getName()方法中返回的字符串,在js調(diào)用的時(shí)候會(huì)使用到。
封裝好了MyNetMoudule模塊。我們還需要在ReactPackage中對(duì)這個(gè)模塊進(jìn)行注冊(cè)。注冊(cè)的代碼如下。
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();
}
}
上面的代碼主要是寫一個(gè)RCTCommonToolsPackage 類繼承于ReactPackage.并在里面實(shí)現(xiàn)其三個(gè)方法。在createNativeModules方法里面注冊(cè)我們自己定義的模塊
注冊(cè)完成后,我們還需要在MainApplication里面對(duì)我們自定義的package進(jìn)行注冊(cè)。主要代碼如下
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RCTCommonToolsPackage(),
new ReactImageZoom()
);
}
};
到了這里,我們的自定義網(wǎng)絡(luò)模塊封裝完畢。
接下來是使用。
'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