前段時間看了些關于RxJava的文章和代碼,感覺雖然講的很透徹,奈何理解的比較少,只會用一些最基礎的方法。囧
昨天發現了一個RxJava的視頻,好吧,我還是感覺看視頻學的比較快...
下載地址
這篇文章主要是對昨天看的視頻的回顧
引子
現在我需要幾個計算器,幫我計算物品的單價,這個肯定很簡單的啦,代碼直接貼出來好了
public class CalcService {
public int calc(int total, int amount) {
int result = result = total / amount;
return result;
}
}
調用這個計算方法
public class MainActivity extends AppCompatActivity {
@Bind(R.id.btn1)
Button btn1;
private CalcService calc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
calc = new CalcService();
}
@OnClick(R.id.btn1)
public void onClick() {
int result = calc.calc(20,5);
Log.e("result",result+"");
}
}
現在問題來了
我的計算器有點老化了,計算問題特別慢,得緩兩秒才能得到答案,怎么搞
public class CalcService {
public int calc(int total, int amount) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int result = result = total / amount;
return result;
}
}
在實際案例中,計算方法會包含大量的耗時操作,比如網絡請求,數據庫操作等等
現在運行程序發現問題所在了
這就是android中常見的阻塞線程,而如果不解決這個問題,很可能出現ANR異常
如何解決這個問題呢?
以前的我是這么做的,不是阻塞線程嗎,我放到子線程中執行不就行了?
于是會出現這樣的代碼
public class CalcService {
int result;
public int calc(final int total, final int amount) {
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = total / amount;
}
}.start();
return result;
}
}
運行之后,又出現問題了,第一次運行的時候值是0,第二次就是正確的值了
這是為什么呢?
這是因為第二次請求是得到上一次的結果
因為這個值是兩秒之后算出來的,但是在算之前就把result的默認值,也就是0,返回出去了
而第二次請求的時候,result已經被賦值為4了,他還是沒有等待2秒之后的值,而是把這個4直接返回出去了
這就是所謂的開啟異步請求獲取數據
如何得到正確的值呢?
這個時候,我們就需要 監聽回調了
改一下代碼
@OnClick(R.id.btn1)
public void onClick() {
calc.calc(20,5,this);
}
public void onSuccess(int result){
Log.e("result",result+"");
}
這里的區別就是傳的值發生改變了,計算器不給力,那我把自己傳過去,你算完了告訴我,省的我還得等著,啥時候完了告訴我一聲就行了
public class CalcService {
int result;
public void calc(final int total, final int amount, final MainActivity activity) {
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = total / amount;
activity.onSuccess(result);
}
}.start();
}
}
這里回調onSuccess(result) 方法,將result數據傳回去就行了
那有了onSuccess()方法,如果出現問題了,比如除數是0,是不是需要一個onFail()方法呢?
那如果調用calc()方法的不是MainActivity,而是別的地方,這該怎么修改呢?
面向接口編程
public interface OnResultListener{
void onSuccess(int result);
void onFail();
}
public void calc(final int total, final int amount, final OnResultListener resultListener) {
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
result = total / amount;
resultListener.onSuccess(result);
} catch (Exception e) {
e.printStackTrace();
resultListener.onFail();
}
}
}.start();
}
這樣只有需要calc()方法的地方,實現OnResultListener接口就可以調用這個方法了
通過監聽回調的形式進行解耦
public class MainActivity extends AppCompatActivity implements CalcService.OnResultListener{
@Bind(R.id.btn1)
Button btn1;
private CalcService calc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
calc = new CalcService();
}
@OnClick(R.id.btn1)
public void onClick() {
calc.calc(20,5,this);
}
@Override
public void onSuccess(int result){
Log.e("result",result+"");
}
@Override
public void onFail() {
}
}
更進一步
如何向點擊事件一樣,寫一個內部類形式的呢?
其實很簡單,只需要寫一個setOnResultListener(OnResultListener resultListener) 方法即可完美解決
private OnResultListener resultListener;
public void setOnResultListener(OnResultListener resultListener){
this.resultListener = resultListener;
}
public void calc(final int total, final int amount) {
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
result = total / amount;
if(resultListener!=null){
resultListener.onSuccess(result);
}
} catch (Exception e) {
e.printStackTrace();
resultListener.onFail();
}
}
}.start();
}
調用起來
@OnClick(R.id.btn1)
public void onClick() {
calc.calc(10,2);
calc.setOnResultListener(new CalcService.OnResultListener() {
@Override
public void onSuccess(int result) {
Log.e("success",result+"");
}
@Override
public void onFail() {
}
});
}
設計模式真的是很神奇,讓代碼的美展現的淋漓盡致
感謝大家喜歡