最近react-native(以下简称rn)的技术越来越活,国内的使用情况也越来越多,国内的氛围也越来越好,其实我是从去年就接触了一下rn,当时我学习了一个多星期,然后刚好处于要换工作就没有学习了,刚好最近有点空闲的时间,就再次去学习,只能说rn的更新速度太快了,很多之前的写法都变了,只能从头开始,但是一整个项目都采用rn来构建还不是很现实,所以国内很多的也是集成rn,所以我也来凑凑热闹。
1:添加依赖
compile "com.facebook.react:react-native:+" // From node_modules
在项目的build.gradle下添加
allprojects {
repositories {
mavenLocal()
jcenter()
maven {
// All of React Native (JS, Android binaries) is installed from npm
url "$rootDir/node_modules/react-native/android"
}
}
}
2:在app的实现ReactApplication接口,以下是部分代码
*/
public class App extends Application implements ReactApplication{
private static App appContext;
private static AppComponent mAppComponent;
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
);
}
};
3:在AndroidManifest.xml加入
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
加入以下的activity可以在摇一摇出现rn的配置页面。
4:写个activity来继承ReactActivity
public class MainActivity extends ReactActivity {
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "MyHot";
}
}
在这里介绍一篇大帅写的React Native 0.31 Bundle 预加载优化主要解决从原生页面到rn页面会有短暂的白屏。使用方法
dependencies {
compile "com.github.moduth:react-native-preloader:0.31.0"
}
把之前继承ReactActivity变成继承MrReactActivity
public class MyReactActivity extends MrReactActivity {
public static final ReactInfo reactInfo = new ReactInfo("MyHot", null);
@Override
protected String getMainComponentName() {
return reactInfo.getMainComponentName();
}
@Override
public ReactInfo getReactInfo() {
return reactInfo;
}
}
在调用rn页面调用
ReactPreLoader.init(this, MyReactActivity.reactInfo);
这样就能很好的解决上述的问题。
在rn中我引入了redux,以下就贴出关键行代码,在最外层
import configureStore from './store/store.js'
import App from './containes/App.js'
const store = configureStore();
class rootApp extends Component {
render() {
return (
<Provider store={store}>
<App/>
</Provider>
)
}
}
export default rootApp;
同时个actions的文件夹里面放着各种的操作,以下是我的newsList的代码
import * as types from "../constants/ActionTypes.js";
import * as Services from "../utils/Services.js";
import {
NEW_LIST
} from "../constants/Urls.js";
export function fetchNews(loading, isRefresh, isLoadMore, pn) {
return dispatch => {
dispatch(fetchNewsList(loading, isRefresh, isLoadMore));
Services.getNewList(NEW_LIST, pn)
.then(result => {
dispatch(receiveNewsList(result));
});
}
}
function fetchNewsList(loading, isRefresh, isLoadMore) {
return {
type: types.FE_NEWLIST,
loading: loading,
isRefresh: isRefresh,
isLoadMore: isLoadMore
};
}
function receiveNewsList(newsList) {
return {
type: types.RE_NEWLIST,
newsList: newsList
}
}
还有就是ruducers文件夹下的和action所对应的
import * as types from '../constants/ActionTypes';
const initialState = {
loading: true,
isRefresh: false,
isLoadMore: false,
newsList: []
}
export default function revicesNewsList(state = initialState, action) {
switch (action.type) {
case types.FE_NEWLIST:
return Object.assign({}, state, {
loading: action.loading,
isRefresh: action.isRefresh,
isLoadMore: action.isLoadMore,
});
case types.RE_NEWLIST:
return Object.assign({}, state, {
loading: false,
isRefresh: false,
isLoadMore: false,
newsList: state.isLoadMore ? state.newsList.concat(action.newsList) : action.newsList,
});
default:
return state;
}
}
还有就是一个转化的
import {
connect
} from 'react-redux';
import News from "../pages/News.js";
import {
bindActionCreators
} from 'redux';
import * as newsAction from '../actions/newsList.js';
class NewsContainer extends Component {
render() {
return (
<News {...this.props} />
);
}
}
function mapStateToProps(state) {
const {
news
} = state;
return {
news
}
}
function mapDispatchToProp(dispatch) {
return {
actions: bindActionCreators(newsAction, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProp)(NewsContainer);
这样在使用的时候就是调用action的方法
componentDidMount() {
const {
actions
} = this.props;
actions.fetchNews(true, false, false, page);
}
接受到数据
render() {
const {
navigator,
news
} = this.props;
return (
<View style={styles.container}>
<Header title="体育" navigator= {navigator}/>
{this.renderContent()}
</View>
)
}
这样以后要是添加新的页面就很清楚了,在action里面添加动作,在reducers添加action的处理器,这样就很清晰了。
我添加了一个Services,来获取数据
const HOST = "http://apis.baidu.com/";
import FetchHttpClient, {
query,
header
} from 'fetch-http-client';
import {
toastShort
} from "./ToastUtil.js";
let client = new FetchHttpClient(HOST);
export function getNewList(url, pnSize) {
return getClient().get(url, {
query: {
num: 10,
pn: pnSize
},
}).then(filterJSON)
.then(filterStatus)
.catch((error) => {
toastShort('网络发生错误,请重试!')
});
}
function getClient() {
client.addMiddleware(query());
client.addMiddleware(request => {
request.options.headers['apikey'] = 'ff27ef67506b2c0738a3252b01f8d564';
});
return client;
}
function filterStatus(res) {
if (res.code === 200) {
return res.newslist;
} else {
toastShort(res.msg);
}
}
function filterJSON(res) {
return res.json();
}
本人rn的水平有限,要是有不对的地方,还请指出和谅解。本文的所以代码在github地址,欢迎star。