這段時間研究了一下rxJava,rxAndroid。對於剛接觸RxJava的人來說,完全是迷茫狀態。相信看了大神的博文之後,心裏有這樣一個疑問,我只是想學rxJava,lambda和Retrofit又是什麼鬼,完全看不懂了。.
所以這篇博文主要是單獨講RxJava在Android中的運用。
一、RxJava是什麼?
二、RxJava感覺很牛B,但是又有什麼用?
三、我要怎麼才能利用RxJava的反應式編程減少在Android中的代碼量?
一、RxJava是什麼?
一個詞:異步。
把這個看作異步的另外一種方式就很好理解了。它是跟AsyncTask,Handler放在一起作比較的。
舉一個例:通過天氣API獲取結果。
需導入RxJava.jar,RxAndroid.jar或者依賴
首先有一個方法:根據API同步獲得請求結果
//控件
TextView tv;
public static final String url_weatherApi = "http://wthrcdn.etouch.cn/weather_mini?city=北京";
// okhttp 同步的get請求
private String requestGet(String url)
Handler:
new Thread(new Runnable() {
@Override
public void run() {
final String requestGet = requestGet(url_weatherApi);
tv.post(new Runnable() {
@Override
public void run() {
tv.setText(requestGet);
}
});
}
}).start();
AsyncTask:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyTask().execute(url_weatherApi);
}
private class MyTask extends AsyncTask<String, String, String>{
@Override
protected String doInBackground(String... params) {
String result = requestGet(params[0]);
return result;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
tv.setText(result);
}
}
RxJava:
Observable.just(url_weatherApi)
.map(new Func1<String, String>() {
//第一個String是參數,即params = url_wetherApi,第二個String是返回結果(用法詳見其他博文)
@Override
public String call(String params) {
return requestGet(params);
}
.subscribeOn(Schedulers.io()) //在io線程(子線程)中操作map轉換操作
.observeOn(AndroidSchedulers.mainThread())//在主線程中運行->subscribe裏面的
.subscribe(new Action1<String>() {
@Override
public void call(String result) {
//上面return的String
tv.setText(result);
}
});
第一眼看起來RxJava似乎更復雜了,對於初學的確是這樣。但是當你用習慣了之後,你會發現這個比handler好用很多(ps.可能吧,博主現在也用的不是很習慣,但我從來不用AsyncTask,總感覺這個太重了=。=)。
二、RxJava感覺很牛B,但是又有什麼用?
rxJava比其他好用之處就在於當你會了之後,看rxJava寫的代碼條理清晰。
比如
{
"desc": "OK",
"status": 1000,
"data": {
"wendu": "25",
"ganmao": "各項氣象條件適宜,無明顯降溫過程,發生感冒機率較低。",
"forecast": [
{
"fengxiang": "無持續風向",
"fengli": "微風級",
"high": "高溫 28℃",
"type": "多雲",
"low": "低溫 15℃",
"date": "29日星期五"
},
{
"fengxiang": "無持續風向",
"fengli": "微風級",
"high": "高溫 31℃",
"type": "晴",
"low": "低溫 15℃",
"date": "30日星期六"
},
{
"fengxiang": "無持續風向",
"fengli": "微風級",
"high": "高溫 32℃",
"type": "多雲",
"low": "低溫 19℃",
"date": "1日星期天"
},
{
"fengxiang": "北風",
"fengli": "4-5級",
"high": "高溫 23℃",
"type": "陣雨",
"low": "低溫 13℃",
"date": "2日星期一"
},
{
"fengxiang": "北風",
"fengli": "4-5級",
"high": "高溫 27℃",
"type": "晴",
"low": "低溫 13℃",
"date": "3日星期二"
}
],
"yesterday": {
"fl": "3-4級",
"fx": "南風",
"high": "高溫 26℃",
"type": "多雲",
"low": "低溫 13℃",
"date": "28日星期四"
},
"aqi": "219",
"city": "北京"
}
}
現在我想取json中yesterday的date。那麼在thread中是這樣的:
new Thread(new Runnable() {
@Override
public void run() {
final String requestGet = requestGet(url_weatherApi);
JSONObject data=null;
try {
JSONObject json = new JSONObject(requestGet);
data = json.getJSONObject("data");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Gson gson = new Gson();
final DataBean dataBean = gson.fromJson(data.toString(), DataBean.class);
tv.post(new Runnable() {
@Override
public void run() {
tv.setText(dataBean.getYesterday().getDate());
}
});
}
}).start();
在rxJava:
Observable.just(url_weatherApi)
//把url轉成json
.map(new Func1<String, String>() {
@Override
public String call(String params) {
return requestGet(params);
}})
//把json轉爲DataBean對象
.map(new Func1<String, DataBean>() {
@Override
public DataBean call(String arg0) {
JSONObject data=null;
try {
JSONObject json = new JSONObject(arg0);
data = json.getJSONObject("data");
} catch (JSONException e) {
e.printStackTrace();
}
Gson gson = new Gson();
DataBean dataBean = gson.fromJson(data.toString(), DataBean.class);
return dataBean;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<DataBean>() {
@Override
public void call(DataBean arg0) {
tv.setText(arg0.getYesterday().getDate());
}});
}
先不管代碼量如何。至少我的思路很清晰,我以後需要改什麼東西,直接可以很清楚的知道哪裏我需要改。而不需要像Thread那樣到處去找代碼。
現在我有一個需求,在獲取了北京的天氣後,再獲取深圳的天氣。並分別給TextView賦值。
public static final String url_weatherApi = "http://wthrcdn.etouch.cn/weather_mini?city=北京";
public static final String url_weatherApi_sz = "http://wthrcdn.etouch.cn/weather_mini?city=深圳";
看一下常規方法。
new Thread(new Runnable() {
@Override
public void run() {
final String requestGet = requestGet(url_weatherApi);
tv.post(new Runnable() {
@Override
public void run() {
Log.e("first", requestGet);
tv.setText(requestGet);
new Thread(new Runnable() {
@Override
public void run() {
final String requestGet = requestGet(url_weatherApi_sz);
tv.post(new Runnable() {
@Override
public void run() {
Log.e("second", requestGet);
tv.setText(requestGet);
}
});
}
}).start();
}
});
}
}).start();
這就是所謂的callback hell。
接下來看看RxJava
Observable.just(url_weatherApi)
//子線程取北京天氣
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.map(new Func1<String, String>() {
@Override
public String call(String arg0) {
return requestGet(arg0);
}
})
//主線程賦值
.observeOn(AndroidSchedulers.mainThread())
.map(new Func1<String,String>() {
@Override
public String call(String arg0) {
Log.e("first", arg0);
tv.setText(arg0);
//返回深圳天氣的url
return url_weatherApi_sz;
}
})
//子線程取深圳天氣
.observeOn(Schedulers.io())
.map(new Func1<String, String>() {
@Override
public String call(String arg0) {
return requestGet(arg0);
}
.observeOn(AndroidSchedulers.mainThread())
//主線程賦值
.subscribe(new Action1<String>() {
@Override
public void call(String arg0) {
Log.e("second", arg0);
tv.setText(arg0);
}
});
好處就不多說了,大家自己體會。
三、我要怎麼才能利用RxJava的反應式編程減少在Android中的代碼量?
利用java 8的新特性lambda
android studio中用retrolambda這個插件。
詳見深入淺出RxJava(一:基礎篇)
好了,rxJava在Android中使用基本使用就到這裏了。
接下來是RxAndroid在Android中的使用。
RxBinding(需導入RxBinding.jar)。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
iv = (ImageView) findViewById(R.id.imageView);
ev1 = (EditText) findViewById(R.id.editText1);
ev2 = (EditText) findViewById(R.id.editText2);
cb = (CheckBox) findViewById(R.id.checkBox1);
//ev1的內容狀態監聽,相當於ev1.addTextChangedListener(watcher),只不過比他好用。
RxTextView.textChanges(ev1).subscribe(new Action1<CharSequence>() {
@Override
public void call(CharSequence arg0) {
tv.setText(arg0);
}
});
}
//監聽checkBox的狀態
RxCompoundButton.checkedChanges(cb).subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean arg0) {
if(arg0){
iv.setVisibility(View.VISIBLE);
}else{
iv.setVisibility(View.GONE);
}
}
});
ps:RxAndroid實際就是RxJava,在Android中,RxAndroid.jar只有一個用處,就是
.observeOn(AndroidSchedulers.mainThread())
在主線程中運行。而RxBinding只是RxAndroid的衍生品。
以上只是RxAndroid簡單入門,想要提升還得多看大神寫的文章。
參考文獻:
給 Android 開發者的 RxJava 詳解
深入淺出RxJava
RxJava入門指南
我是用Eclipse的,所以Demo也是eclipse的Demo,裏面包含了jar包。