Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發學習之路--RxAndroid之簡單原理

Android開發學習之路--RxAndroid之簡單原理

編輯:關於Android編程

??學習了RxAndroid,其實也就是RxJava了,但是還是不是非常清楚到底RxAndroid有什麼用呢?為什麼要使用RxAndroid呢?這篇文章講得不錯,RxJava的原理。但是這裡還是把整個過程學習下,這裡主要參考文章中的原理,再把這個過程實現了一遍,也算是一知半解了。


一般實現

??首先來個簡單的例子,選出一個班級裡面,學生成績最好的,然後保存這個學生的姓名,這裡簡單實現下Student的類。

package com.jared.emrxandroidstudy;

/**
 * Created by jared on 16/3/13.
 */
public class Student implements Comparable {
    String name;
    int grade;

    @Override
    public int compareTo(Student student) {
        return Integer.compare(grade, student.grade);
    }
}

??這裡通過實現Comparable來實現排序,通過成績grade。接著實現StuApi。

package com.jared.emrxandroidstudy;

import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public interface StuApi {
    List queryStudents(String query);
    String store(Student student);
}

??接著實現我們的業務邏輯StudentHelper。

package com.jared.emrxandroidstudy;

import java.util.Collections;
import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StudentHelper {
    StuApi stuApi;

    public String saveTheBestStudent(String query) {
        List students = stuApi.queryStudents(query);
        Student best = findBest(students);
        String saveName = stuApi.store(best);
        return saveName;
    }

    private Student findBest(List students) {
        return Collections.max(students);
    }
}

??這裡實現了saveTheBestStudent的方法,查詢student,獲取學生的鏈表,然後找到grade最大的,然後保存該學生的名字,返回。
??這裡需要經過三個步驟,而且每個步驟都是按順序來實現的,是阻塞的方式的。
??如果查詢student花了很長時間的話,那麼程序不應該一直在這裡,我們需要的是處理完了告訴我們,而不是一直等著,就拿Android的click事件,當我們按下了button,才會觸發onClick回調函數。那麼接下去我們來實現下吧。

異步實現

??修改StuApi如下:

package com.jared.emrxandroidstudy;

import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public interface StuApi {
    interface StudentsCallback {
        void onStudentsListGetOk(List students);
        void onQueryFailed(Exception e);
    }

    interface StoreCallback {
        void onStudentStored(String name);
        void onStoreFailed(Exception e);
    }

    void queryStudents(String query, StudentsCallback studentsCallback);
    void store(Student student, StoreCallback storeCallback);
}

??這裡實現了StudentsCallback回調函數接口,當queryStudent成功的時候會回調onStudentsListGetOk,當失敗的時候會調用onQueryFailed。StoreCallback回調函數接口,當store成功的時候回調onStudentStored,當失敗的時候回調onStoreFailed。
??接著修改StudentHelper:

package com.jared.emrxandroidstudy;

import java.util.Collections;
import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StudentHelper {

    public interface BestStudentCallback {
        void onBestStudentSaved(String name);
        void onError(Exception e);
    }

    StuApi stuApi;

    public void saveTheBestStudent(String query, BestStudentCallback bestStudentCallback) {
        stuApi.queryStudents(query, new StuApi.StudentsCallback() {
            @Override
            public void onStudentsListGetOk(List students) {
                Student best = findBest(students);
                stuApi.store(best, new StuApi.StoreCallback() {
                    @Override
                    public void onStudentStored(String name) {
                        bestStudentCallback.onBestStudentSaved(name);
                    }

                    @Override
                    public void onStoreFailed(Exception e) {
                        bestStudentCallback.onError(e);
                    }
                });
            }

            @Override
            public void onQueryFailed(Exception e) {
                bestStudentCallback.onError(e);
            }
        });
    }

    private Student findBest(List students) {
        return Collections.max(students);
    }
}

??這裡實現了BestStudentCallback回調函數接口,當query成功的時候調用store方法,接著當store成功後回調onStudentStored方法,當失敗後回調onBestStudentSaved,當失敗的時候調用onError。
??回調嵌套著回調,而且錯誤傳遞也是問題,分不清哪個錯誤,代碼也失去了最開始阻塞方式的那種簡潔優雅。

泛型回調實現

??實現泛型回調Callback:

package com.jared.emrxandroidstudy;

/**
 * Created by jared on 16/3/12.
 */
public interface Callback {
    void onResult(T result);
    void onError(Exception e);
}

??這裡實現泛型回調函數Callback,實現兩個方法,成功onResult,失敗onError,成功傳入的參數是泛型的,失敗統一的Exception。接著添加StuApiWrapper,實現如下:

package com.jared.emrxandroidstudy;

import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StuApiWrapper {
    StuApi stuApi;

    public void queryStudents(String query, Callback> listCallback) {
        stuApi.queryStudents(query, new StuApi.StudentsCallback() {
            @Override
            public void onStudentsListGetOk(List students) {
                listCallback.onResult(students);
            }

            @Override
            public void onQueryFailed(Exception e) {
                listCallback.onError(e);
            }
        });
    }

    public void store(Student student, Callback callback) {
        stuApi.store(student, new StuApi.StoreCallback() {
            @Override
            public void onStudentStored(String name) {
                callback.onResult(name);
            }

            @Override
            public void onStoreFailed(Exception e) {
                callback.onError(e);
            }
        });
    }
}

??實現queryStudents和store兩個方法,接著修改StudentHelper如下:

package com.jared.emrxandroidstudy;

import java.util.Collections;
import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StudentHelper {

    StuApiWrapper stuApiWrapper;

    public void saveTheBestStudent(String query, Callback bestStuCallback) {
        stuApiWrapper.queryStudents(query, new Callback>() {
            @Override
            public void onResult(List result) {
                Student student = findBest(result);
                stuApiWrapper.store(student, bestStuCallback);
            }

            @Override
            public void onError(Exception e) {
                bestStuCallback.onError(e);
            }
        });
    }

    private Student findBest(List students) {
        return Collections.max(students);
    }
}

AsyncJob實現

??這裡saveTheBestStudent傳入一個回調,當queryStudents成功後,會回調stuApiWrapper.store,然後成功的話,會在傳入的bestStuCallback回調onStudentStored。
??顯然這樣還是沒有達到簡潔明了,還需要傳遞回調函數,還是覺得麻煩,這裡引入AsyncJob。

package com.jared.emrxandroidstudy;

/**
 * Created by jared on 16/3/12.
 */
public abstract class AsyncJob {
    public abstract void start(Callback callback);
}

??如果在異步操作中返回一些臨時對象,我們需要定義一個類出來。這樣的一個對象需要包括常見的行為(以回調為單一參數)。
??修改StuApiWrapper如下:

package com.jared.emrxandroidstudy;

import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StuApiWrapper {
    StuApi stuApi;

    public AsyncJob> queryStudents(String query) {
        return new AsyncJob>() {
            @Override
            public void start(Callback> callback) {
                stuApi.queryStudents(query, new StuApi.StudentsCallback() {
                    @Override
                    public void onStudentsListGetOk(List students) {
                        callback.onResult(students);
                    }

                    @Override
                    public void onQueryFailed(Exception e) {
                        callback.onError(e);
                    }
                });
            }
        };
    }

    public AsyncJob store(Student student) {
        return new AsyncJob() {
            @Override
            public void start(Callback callback) {
                stuApi.store(student, new StuApi.StoreCallback() {
                    @Override
                    public void onStudentStored(String name) {
                        callback.onResult(name);
                    }

                    @Override
                    public void onStoreFailed(Exception e) {
                        callback.onError(e);
                    }
                });
            }
        };
    }
}

??這裡泛型抽象類AsyncJob實現了queryStudents和store,返回的數據都是AsyncJob。接著看看StudentHelper怎麼來實現:

package com.jared.emrxandroidstudy;

import java.util.Collections;
import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StudentHelper {

    StuApiWrapper stuApiWrapper;

    public AsyncJob saveTheBestStudent(String query) {
        return new AsyncJob() {
            @Override
            public void start(Callback bestStudentcallback) {
                stuApiWrapper.queryStudents(query)
                        .start(new Callback>() {
                            @Override
                            public void onResult(List result) {
                                Student best = findBest(result);
                                stuApiWrapper.store(best)
                                        .start(new Callback() {
                                            @Override
                                            public void onResult(String result) {
                                                bestStudentcallback.onResult(result);
                                            }

                                            @Override
                                            public void onError(Exception e) {
                                                bestStudentcallback.onError(e);
                                            }
                                        });
                            }

                            @Override
                            public void onError(Exception e) {
                                bestStudentcallback.onError(e);
                            }
                        });
            }
        };
    }

    private Student findBest(List students) {
        return Collections.max(students);
    }
}

??這裡在成功query後回調中找到最好成績的學生,再存儲。失敗就調用onError了。這裡省去了saveTheBestStudent的callback參數,回調都在AsyncJob的start方法裡去實現,傳遞。
??接著我們可以使用 AsyncJob把我們的方法分解成更小的操作。

package com.jared.emrxandroidstudy;

import java.util.Collections;
import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StudentHelper {

    StuApiWrapper stuApiWrapper;

    public AsyncJob saveTheBestStudent(String query) {
        AsyncJob> studentsAsyncJob = stuApiWrapper.queryStudents(query);
        AsyncJob bestStudentAsyncJob = new AsyncJob() {
            @Override
            public void start(Callback callback) {
                studentsAsyncJob.start(new Callback>() {
                    @Override
                    public void onResult(List result) {
                        callback.onResult(findBest(result));
                    }

                    @Override
                    public void onError(Exception e) {
                        callback.onError(e);
                    }
                });
            }
        };

        AsyncJob storeNameAsyncJob = new AsyncJob() {
            @Override
            public void start(Callback callback) {
                bestStudentAsyncJob.start(new Callback() {
                    @Override
                    public void onResult(Student result) {
                        stuApiWrapper.store(result)
                                .start(new Callback() {
                                    @Override
                                    public void onResult(String result) {
                                        callback.onResult(result);
                                    }

                                    @Override
                                    public void onError(Exception e) {
                                        callback.onError(e);
                                    }
                                });
                    }

                    @Override
                    public void onError(Exception e) {
                        callback.onError(e);
                    }
                });
            }
        };
        return storeNameAsyncJob;
    }

    private Student findBest(List students) {
        return Collections.max(students);
    }
}

??這裡使用了AsyncJob來轉換我們所要的結果,接著我們實現一個轉換方法:

package com.jared.emrxandroidstudy;

/**
 * Created by jared on 16/3/12.
 */
public interface Func {
    R call(T t);
}

??接口有兩個類型成員,T對應於參數類型而R對應於返回類型。
??接著修改AsyncJob:

package com.jared.emrxandroidstudy;

/**
 * Created by jared on 16/3/12.
 */
public abstract class AsyncJob {
    public abstract void start(Callback callback);

    public  AsyncJob map(Func func) {
        final AsyncJob source = this;
        return new AsyncJob() {
            @Override
            public void start(Callback callback) {
                source.start(new Callback() {
                    @Override
                    public void onResult(T result) {
                        R mapped = func.call(result);
                        callback.onResult(mapped);
                    }

                    @Override
                    public void onError(Exception e) {
                        callback.onError(e);
                    }
                });
            }
        };
    }

    public  AsyncJob flatMap(Func> func) {
        final AsyncJob source = this;
        return new AsyncJob() {
            @Override
            public void start(Callback callback) {
                source.start(new Callback() {
                    @Override
                    public void onResult(T result) {
                        AsyncJob mapped = func.call(result);
                        mapped.start(new Callback() {
                            @Override
                            public void onResult(R result) {
                                callback.onResult(result);
                            }

                            @Override
                            public void onError(Exception e) {
                                callback.onError(e);
                            }
                        });
                    }

                    @Override
                    public void onError(Exception e) {
                        callback.onError(e);
                    }
                });
            }
        };
    }
}

??這裡實現了map和flatMap兩個方法,接著修改StudentHelper如下:

package com.jared.emrxandroidstudy;

import java.util.Collections;
import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StudentHelper {

    StuApiWrapper stuApiWrapper;

    public AsyncJob saveTheBestStudent(String query) {
        AsyncJob> bestListAsyncJob = stuApiWrapper.queryStudents(query);
        AsyncJob bestStudentAsyncJob = bestListAsyncJob.map(new Func, Student>() {
            @Override
            public Student call(List students) {
                return findBest(students);
            }
        });

        AsyncJob storeNameAsyncJob = bestStudentAsyncJob.flatMap(new Func>() {
            @Override
            public AsyncJob call(Student students) {
                return stuApiWrapper.store(students);
            }
        });
        return storeNameAsyncJob;
    }

    private Student findBest(List students) {
        return Collections.max(students);
    }
}

lambda實現

??其實代碼已經很簡單了,接著我們通過lambda方式實現如下:

package com.jared.emrxandroidstudy;

import java.util.Collections;
import java.util.List;

/**
 * Created by jared on 16/3/13.
 */
public class StudentHelper {

    StuApiWrapper stuApiWrapper;

    public AsyncJob saveTheBestStudent(String query) {
        AsyncJob> bestListAsyncJob = stuApiWrapper.queryStudents(query);
        AsyncJob bestStudentAsyncJob = bestListAsyncJob.map(students -> findBest(students));
        AsyncJob storeNameAsyncJob = bestStudentAsyncJob.flatMap(student -> stuApiWrapper.store(student));
        return storeNameAsyncJob;
    }

    private Student findBest(List students) {
        return Collections.max(students);
    }
}

RxJava實現

??其實這些都可以使用RxJava來實現,修改StuApiWrapper:

package com.jared.emrxandroidstudy;

import java.util.List;

import rx.Observable;
import rx.Subscriber;

/**
 * Created by jared on 16/3/13.
 */
public class StuApiWrapper {
    StuApi stuApi;

    public Observable> queryStudents(String query) {
        return Observable.create(new Observable.OnSubscribe>() {
            @Override
            public void call(Subscriber> subscriber) {
                stuApi.queryStudents(query, new StuApi.StudentsCallback() {
                    @Override
                    public void onStudentsListGetOk(List students) {
                        subscriber.onNext(students);
                    }

                    @Override
                    public void onQueryFailed(Exception e) {
                        subscriber.onError(e);
                    }
                });
            }
        });
    }

    public Observable store(final Student student) {
        return Observable.create(new Observable.OnSubscribe() {
            @Override
            public void call(Subscriber subscriber) {
                stuApi.store(student, new StuApi.StoreCallback() {
                    @Override
                    public void onStudentStored(String name) {
                        subscriber.onNext(name);
                    }

                    @Override
                    public void onStoreFailed(Exception e) {
                        subscriber.onError(e);
                    }
                });
            }
        });
    }
}

??修改StudentHelper:

package com.jared.emrxandroidstudy;

import java.util.Collections;
import java.util.List;

import rx.Observable;

/**
 * Created by jared on 16/3/13.
 */
public class StudentHelper {

    StuApiWrapper stuApiWrapper;

    public Observable saveTheBestStudent(String query) {
        Observable> bestListObservable = stuApiWrapper.queryStudents(query);
        Observable bestStudentObservable = bestListObservable.map(students -> findBest(students));
        Observable storeNameObservable = bestStudentObservable.flatMap(student -> stuApiWrapper.store(student));
        return storeNameObservable;
    }

    private Student findBest(List students) {
        return Collections.max(students);
    }
}

??我們看到,通過簡單的轉化我們可以把異步操作給抽象出來。這個抽象出來的東西可以被用來操作和組合異步操作就像簡單的方法那樣。通過這種方法我們可以擺脫嵌套的回調,在處理異步結果時也能手動處理錯誤的傳遞。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved