前言
在上一篇我講了Agera的基本概念和原理篱瞎,但是有人估計(jì)會(huì)說(shuō)你這講的是什么呀,看的我好懵逼呀智袭,talk is cheap奔缠,show me your code!我接下來(lái)就結(jié)合demo來(lái)講一下Agera的用法吼野。校哎。
功能分析
接下來(lái)要寫的demo是一個(gè)下拉刷新改變數(shù)據(jù)的demo。這個(gè)功能很常見吧瞳步,在很多的應(yīng)用中都有這個(gè)功能吧闷哆,下拉之后向網(wǎng)絡(luò)發(fā)送請(qǐng)求,然后改變數(shù)據(jù)单起。接下來(lái)利用這個(gè)demo來(lái)更好演示Agera的用法抱怔。
利用回調(diào)
我們很常見的思路就是回調(diào)吧,當(dāng)數(shù)據(jù)加載成功或者失敗后回調(diào)給頁(yè)面嘀倒。因此接下來(lái)就用這種思路完成demo屈留。首先分析下流程:
- 下拉
- 獲取數(shù)據(jù)
- 更新頁(yè)面
因此需要監(jiān)聽下拉這個(gè)事件的觸發(fā)局冰,因此就需要一個(gè)observable同時(shí)實(shí)現(xiàn)OnRefreshListener,就命名為OnRefreshObservable灌危,接著獲取數(shù)據(jù)的對(duì)象需要監(jiān)聽這個(gè)下拉事件康二,又要通知界面更新,因此就需要實(shí)現(xiàn)observable和updatable的責(zé)任勇蝙,同時(shí)又要提供數(shù)據(jù)沫勿,也就也需要實(shí)現(xiàn)Supplier的責(zé)任。那么為什么需要回調(diào)呢味混?因?yàn)橥@取數(shù)據(jù)是一個(gè)耗時(shí)的任務(wù)产雹,我們會(huì)新開一個(gè)線程用于處理,那么當(dāng)他失敗或者成功的時(shí)候使用接口回調(diào)進(jìn)行處理翁锡,就命名為UsernamesRepository蔓挖。最后就是頁(yè)面更新了,頁(yè)面需要監(jiān)聽UsernamesRepository盗誊,也就需要實(shí)現(xiàn)updatable的責(zé)任时甚。流程分析了,就下來(lái)就該寫代碼了
首先先描述一下界面:
#MainActivity
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
#activity_main
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:theme="@style/Toolbar" /> <fragment android:id="@+id/fragment" android:name="com.example.lizheng.myapplication.MainFragment" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
#main_frag
<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.SwipeRefreshLayout android:id="@+id/refresh_layout" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"/></android.support.v4.widget.SwipeRefreshLayout>
布局很簡(jiǎn)單哈踱,fragment由一個(gè)下拉刷新控件內(nèi)嵌套一個(gè)listview組成荒适。mainActivity則是由一個(gè)toolbar和這個(gè)fragment組成。布局寫好了开镣,接下來(lái)就得按著流程來(lái)實(shí)現(xiàn)功能了刀诬。
首先就是需要讓該OnRefreshListener實(shí)現(xiàn)Observable功能
public class OnRefreshObservable extends BaseObservable
implements SwipeRefreshLayout.OnRefreshListener {
//當(dāng)下拉刷新觸發(fā)時(shí)同時(shí)通知監(jiān)聽者更新,這樣就讓OnRefreshListener同時(shí)實(shí)現(xiàn)了observable的功能
@Override
public void onRefresh() {
dispatchUpdate();
}
}
接下來(lái)就應(yīng)該實(shí)現(xiàn)獲取數(shù)據(jù)的功能:
#UsernamesFetcher
//具體獲取姓名數(shù)據(jù)
public class UsernamesFetcher {
//模擬數(shù)據(jù)數(shù)量為4
public static int NUMBER_OF_USERS = 4;
//模擬獲取數(shù)據(jù)邪财,采取新線程異步加載陕壹,利用接口回調(diào)
public void getUsernames(final UsernamesCallback callback) {
if (NUMBER_OF_USERS < 0) {
callback.setError();
return;
}
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000); //模擬網(wǎng)絡(luò)耗時(shí)
// Create a fake list of usernames
Log.i("MainActivity","current "+Thread.currentThread().getName()+" "+currentThread().getId());
String name1 = "Joe";
String name2 = "Amanda";
final List<String> usernames = new ArrayList<String>();
Random random = new Random();
for (int i = 0; i < NUMBER_OF_USERS; i++) {
int number = random.nextInt(50);
if (System.currentTimeMillis() % 2 == 0) {
usernames.add(name1 + number);
} else {
usernames.add(name2 + number);
}
}
callback.setUsernames(usernames.toArray(new String[usernames.size()]));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
//回調(diào)接口,用于區(qū)分?jǐn)?shù)據(jù)獲取成功還是失敗
public interface UsernamesCallback {
void setError();
void setUsernames(String[] usernames);
}
}```
上面這個(gè)類是具體的獲取數(shù)據(jù)的類树埠,里面封裝了獲取數(shù)據(jù)的函數(shù)和相關(guān)回調(diào)接口糠馆。之后便是最為關(guān)鍵的UsernamesRepository:
//該類需要實(shí)現(xiàn)observable,updatable和supplier功能
public class UsernamesRepository extends BaseObservable
implements Supplier<String[]>, Updatable, UsernamesFetcher.UsernamesCallback {
private String[] usernames;//姓名數(shù)據(jù)列表
private boolean lastRefreshError;//用于判定是否更新成功
private final UsernamesFetcher usernamesFetcher;
public UsernamesRepository(UsernamesFetcher usernamesFetcher) {
super();
this.usernamesFetcher = usernamesFetcher;
}
/**
* 獲取最新的數(shù)據(jù)怎憋,繼承自Supplier
*/
@NonNull
@Override
public String[] get() {
return usernames;
}
/**
* 返回值表示最近更新是否成功
*/
public boolean isError() {
return lastRefreshError;
}
/**
* 繼承自u(píng)pdatable又碌,更新姓名數(shù)據(jù)
*/
@Override
public void update() {
usernamesFetcher.getUsernames(this);
}
/**
* 當(dāng)數(shù)據(jù)獲取失敗時(shí),回調(diào)接口調(diào)用
*/
@Override
public void setError() {
lastRefreshError = true;
dispatchUpdate(); //通知UsernamesRepositoryuser的監(jiān)聽者更新
}
/**
* 獲取數(shù)據(jù)成功時(shí)調(diào)用
*/
@Override
public void setUsernames(String[] usernames) {
this.usernames = usernames;
lastRefreshError = false;
dispatchUpdate();
}
/**
* 當(dāng)從0個(gè)監(jiān)聽者到1個(gè)監(jiān)聽者時(shí)調(diào)用绊袋。
*/
@Override
protected void observableActivated() {
update();
}
}```
之后就是MainFragment:
public class MainFragment extends Fragment implements Updatable {
private OnRefreshObservable refreshObservable;
private UsernamesRepository usernamesRepository;
private ListAdapter listAdapter;
private ListView listView;
private SwipeRefreshLayout swipeRefreshLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.main_frag, container, false);
listView = (ListView) root.findViewById(R.id.list);
//設(shè)置下拉刷新相關(guān)設(shè)置并且將監(jiān)聽器綁定到view上毕匀,這樣,refreshObservable就設(shè)置好了
refreshObservable = new OnRefreshObservable();
swipeRefreshLayout = (SwipeRefreshLayout) root.findViewById(R.id.refresh_layout);
swipeRefreshLayout.setColorSchemeColors(
ContextCompat.getColor(getActivity(), R.color.colorPrimary),
ContextCompat.getColor(getActivity(), R.color.colorAccent),
ContextCompat.getColor(getActivity(), R.color.colorPrimaryDark));
swipeRefreshLayout.setOnRefreshListener(refreshObservable);
// 初始化UsernamesRepository
usernamesRepository = new UsernamesRepository(new UsernamesFetcher());
return root;
}
@Override
public void onResume() {
super.onResume();
//使repository監(jiān)聽refreshObservable
refreshObservable.addUpdatable(usernamesRepository);
//mainFragment監(jiān)聽repository
usernamesRepository.addUpdatable(this);
// 確保每次進(jìn)入應(yīng)用時(shí)顯示刷新動(dòng)畫
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
}
});
}
@Override
public void onPause() {
super.onPause();
//避免內(nèi)存泄漏癌别,移除觀察者
refreshObservable.removeUpdatable(usernamesRepository);
usernamesRepository.removeUpdatable(this);
}
@Override
public void update() {
//更新完數(shù)據(jù)后取消動(dòng)畫
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
});
// 檢查數(shù)據(jù)獲取錯(cuò)誤
if (usernamesRepository.isError()) {
Toast.makeText(getContext(), getResources().getString(R.string.error),
Toast.LENGTH_LONG).show();
} else {
// 更新頁(yè)面數(shù)據(jù)
listAdapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_list_item_1, usernamesRepository.get());
listView.setAdapter(listAdapter);
}
}
}
MainActivity則是簡(jiǎn)單的幾行代碼:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
既然代碼寫好了皂岔,接下來(lái)就結(jié)合代碼分析下事件的流程,但是要想知道代碼如何運(yùn)行展姐,就要先知道Agera的事件傳遞機(jī)制:
- observable首次添加updatable->addUpdatable(Updatable)->workerhandler(handler.obtainMessage(WorkerHandler.MSG_FIRST_ADDED, this).sendToTarget();)->workerHandler.callFirstUpdatableAdded()->observable.observableActivated().
- 當(dāng)observable發(fā)出事件->調(diào)用dispatchUpdate()->workerhandler發(fā)送信息(handler.obtainMessage(MSG_UPDATE, this).sendToTarget();)->workerhandler調(diào)用sendUpdate()->如果是當(dāng)前線程和添加updatable時(shí)所在的線程是同一線程躁垛,監(jiān)聽者直接開始update,否則workhandler發(fā)送消息(handler.obtainMessage(WorkerHandler.MSG_CALL_UPDATABLE, updatable).sendToTarget();)剖毯,然后updatable更新。
- 當(dāng)observable移除最后一個(gè)updatable->removeUpdatable(Updatable)->workerhandler發(fā)送信息(handler.obtainMessage(MSG_LAST_REMOVED, this).sendToTarget();)->workerHandler調(diào)用callLastUpdatableRemoved()->observable.observableDeactivated()
上面講了Agera的幾個(gè)事件的傳遞流程教馆,接下來(lái)就結(jié)合demo分析代碼的執(zhí)行流程了:
- 進(jìn)入應(yīng)用 onResume()->為refreshObservable添加監(jiān)聽者usernamesRepository->為usernamesRepository添加監(jiān)聽者M(jìn)ainFragment->(中間省略了一些Agera的傳遞)usernamesRepository.observableActivated->usernamesRepository.update(重寫了observableActivated()速兔,調(diào)用了update())->swipeRefreshLayout.setRefreshing(true)(進(jìn)入應(yīng)用時(shí)顯示刷新動(dòng)畫)->MainFragment.update().這樣當(dāng)進(jìn)入界面的時(shí)候就更新完畢了。
- 下拉刷新觸發(fā)OnRefreshObservable.onRefresh()->(重寫了onRefresh方法)dispatchUpdate()(繼承自BaseObservable)->(省略了Agera的傳遞機(jī)制)UsernamesRepository.update()->usernamesFetcher.getUsernames()獲取數(shù)據(jù)->如果獲取成功UsernamesRepository調(diào)用setUsernames活玲,否則調(diào)用serError->dispatchUpdate()(繼承自BaseObservable)->MainFragment開始updata()。這樣一次下拉刷新就完成了數(shù)據(jù)的更新谍婉。
- 退出應(yīng)用或者使其成為后臺(tái)應(yīng)用一定會(huì)發(fā)生onpause()->refreshObservable.removeUpdatable(usernamesRepository)為refreshObservable移除監(jiān)聽者->refreshObservable.observableDeactivated()->usernamesRepository.removeUpdatable(this)為usernamesRepository移除監(jiān)聽者->usernamesRepository.observableDeactivated().這樣但不需要下拉刷新的時(shí)候就移除觀察者使其不能再刷新數(shù)據(jù)舒憾,同時(shí)這也是為了避免內(nèi)存泄漏。讓observable添加和刪除updatable與fragment等的生命周期相對(duì)應(yīng)穗熬。
利用CompiledRepository
首先你得知道Repository是什么吧
public interface Repository<T> extends Observable, Supplier<T> {}
所以我們知道repository實(shí)現(xiàn)了被觀察者的作用同時(shí)也能提供數(shù)據(jù)镀迂。那么CompiledRepository
final class CompiledRepository extends BaseObservable implements Repository, Updatable, Runnable{
...
}
那么如何使用它呢?
public class MainFragment extends Fragment implements Updatable {
private OnRefreshObservable refreshObservable;
private Repository<Result<List<String>>> usernamesRepository;
private ListAdapter listAdapter;
private ListView listView;
private SwipeRefreshLayout swipeRefreshLayout;
private ExecutorService networkExecutor;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.main_frag, container, false);
listView = (ListView) root.findViewById(R.id.list);
refreshObservable = new OnRefreshObservable();
swipeRefreshLayout = (SwipeRefreshLayout) root.findViewById(R.id.refresh_layout);
swipeRefreshLayout.setColorSchemeColors(
ContextCompat.getColor(getActivity(), R.color.colorPrimary),
ContextCompat.getColor(getActivity(), R.color.colorAccent),
ContextCompat.getColor(getActivity(), R.color.colorPrimaryDark));
swipeRefreshLayout.setOnRefreshListener(refreshObservable);
setUpRepository();
return root;
}
private void setUpRepository() {
//后臺(tái)執(zhí)行
networkExecutor = newSingleThreadExecutor();
//設(shè)置repository唤蔗,關(guān)鍵代碼
usernamesRepository = Repositories
.repositoryWithInitialValue(Result.<List<String>>absent())
.observe(refreshObservable)
.onUpdatesPerLoop()
.goTo(networkExecutor)
.thenGetFrom(new UsernamesSupplier())
.compile();
}
@Override
public void onResume() {
super.onResume();
usernamesRepository.addUpdatable(this);
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
update();
}
});
}
@Override
public void onPause() {
super.onPause();
usernamesRepository.removeUpdatable(this);
}
@Override
public void update() {
//進(jìn)行獲取數(shù)據(jù)的判定
//如果拿到的是最初的數(shù)據(jù)就開始刷新
if (usernamesRepository.get().isAbsent()) {
swipeRefreshLayout.setRefreshing(true);
//如果數(shù)據(jù)獲取失敗就提示
} else if (usernamesRepository.get().failed()) {
Toast.makeText(getContext(), getResources().getString(R.string.error),
Toast.LENGTH_LONG).show();
swipeRefreshLayout.setRefreshing(false);
} else {
listAdapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_list_item_1, usernamesRepository.get().get());
listView.setAdapter(listAdapter);
swipeRefreshLayout.setRefreshing(false);
}
}
}```
大部分代碼和之前類似探遵。。而這一句代碼便是CompiledRepository的使用方法
usernamesRepository = Repositories
.repositoryWithInitialValue(Result.<List<String>>absent())
.observe(refreshObservable)
.onUpdatesPerLoop()
.goTo(networkExecutor)
.thenGetFrom(new UsernamesSupplier())
.compile();
感覺沒(méi)有看過(guò)源代碼也能理解這句話妓柜,果然使用很簡(jiǎn)單
.repositoryWithInitialValue(Result.<List<String>>absent())是創(chuàng)建一個(gè)Repository并為其賦初值箱季;
.observe(refreshObservable)表示監(jiān)聽refreshObservable;
.onUpdatesPerLoop()表示更新的頻率
.goTo(networkExecutor)表示將指令在后臺(tái)執(zhí)行
.thenGetFrom(new UsernamesSupplier())表示從UsernamesSupplier中獲取數(shù)據(jù)
.compile得到repository實(shí)例棍掐。但是為什么要這么寫呢藏雏?因?yàn)檫@種repository是有state的,你得按照狀態(tài)一步一步來(lái)
public interface RepositoryCompilerStates {
interface REventSource<TVal, TStart> {
@NonNull
RFrequency<TVal, TStart> observe(@NonNull Observable... observables);
}
interface RFrequency<TVal, TStart> extends REventSource<TVal, TStart> {
@NonNull
RFlow<TVal, TStart, ?> onUpdatesPer(int millis);
@NonNull
RFlow<TVal, TStart, ?> onUpdatesPerLoop();
}
interface RFlow<TVal, TPre, TSelf extends RFlow<TVal, TPre, TSelf>>
extends RSyncFlow<TVal, TPre, TSelf> {
@NonNull
@Override
<TCur> RFlow<TVal, TCur, ?> getFrom(@NonNull Supplier<TCur> supplier);
@NonNull
@Override
<TCur> RTermination<TVal, Throwable, RFlow<TVal, TCur, ?>> attemptGetFrom(
@NonNull Supplier<Result<TCur>> attemptSupplier);
@NonNull
@Override
<TAdd, TCur> RFlow<TVal, TCur, ?> mergeIn(@NonNull Supplier<TAdd> supplier,
@NonNull Merger<? super TPre, ? super TAdd, TCur> merger);
@NonNull
@Override
<TAdd, TCur> RTermination<TVal, Throwable, RFlow<TVal, TCur, ?>> attemptMergeIn(
@NonNull Supplier<TAdd> supplier,
@NonNull Merger<? super TPre, ? super TAdd, Result<TCur>> attemptMerger);
@NonNull
@Override
<TCur> RFlow<TVal, TCur, ?> transform(@NonNull Function<? super TPre, TCur> function);
@NonNull
@Override
<TCur> RTermination<TVal, Throwable, RFlow<TVal, TCur, ?>> attemptTransform(
@NonNull Function<? super TPre, Result<TCur>> attemptFunction);
@NonNull
TSelf goTo(@NonNull Executor executor);
@NonNull
RSyncFlow<TVal, TPre, ?> goLazy();
}
interface RSyncFlow<TVal, TPre, TSelf extends RSyncFlow<TVal, TPre, TSelf>> {
@NonNull
<TCur> RSyncFlow<TVal, TCur, ?> getFrom(@NonNull Supplier<TCur> supplier);
@NonNull
<TCur>
RTermination<TVal, Throwable, ? extends RSyncFlow<TVal, TCur, ?>> attemptGetFrom(
@NonNull Supplier<Result<TCur>> attemptSupplier);
@NonNull
<TAdd, TCur> RSyncFlow<TVal, TCur, ?> mergeIn(@NonNull Supplier<TAdd> supplier,
@NonNull Merger<? super TPre, ? super TAdd, TCur> merger);
@NonNull
<TAdd, TCur>
RTermination<TVal, Throwable, ? extends RSyncFlow<TVal, TCur, ?>> attemptMergeIn(
@NonNull Supplier<TAdd> supplier,
@NonNull Merger<? super TPre, ? super TAdd, Result<TCur>> attemptMerger);
@NonNull
<TCur> RSyncFlow<TVal, TCur, ?> transform(@NonNull Function<? super TPre, TCur> function);
@NonNull
<TCur> RTermination<TVal, Throwable, ? extends RSyncFlow<TVal, TCur, ?>> attemptTransform(
@NonNull Function<? super TPre, Result<TCur>> attemptFunction);
@NonNull
RTermination<TVal, TPre, TSelf> check(@NonNull Predicate<? super TPre> predicate);
@NonNull
<TCase> RTermination<TVal, TCase, TSelf> check(
@NonNull Function<? super TPre, TCase> caseFunction,
@NonNull Predicate<? super TCase> casePredicate);
@NonNull
TSelf sendTo(@NonNull Receiver<? super TPre> receiver);
@NonNull
<TAdd> TSelf bindWith(@NonNull Supplier<TAdd> secondValueSupplier,
@NonNull Binder<? super TPre, ? super TAdd> binder);
@NonNull
RConfig<TVal> thenSkip();
@NonNull
RConfig<TVal> thenGetFrom(@NonNull Supplier<? extends TVal> supplier);
@NonNull
RTermination<TVal, Throwable, RConfig<TVal>> thenAttemptGetFrom(
@NonNull Supplier<? extends Result<? extends TVal>> attemptSupplier);
@NonNull
<TAdd> RConfig<TVal> thenMergeIn(@NonNull Supplier<TAdd> supplier,
@NonNull Merger<? super TPre, ? super TAdd, ? extends TVal> merger);
@NonNull
<TAdd> RTermination<TVal, Throwable, RConfig<TVal>> thenAttemptMergeIn(
@NonNull Supplier<TAdd> supplier,
@NonNull Merger<? super TPre, ? super TAdd,
? extends Result<? extends TVal>> attemptMerger);
/**
* Perform the {@link #transform} directive and use the output value as the new value of the
* compiled repository, with notification if necessary.
*/
@NonNull
RConfig<TVal> thenTransform(
@NonNull Function<? super TPre, ? extends TVal> function);
@NonNull
RTermination<TVal, Throwable, RConfig<TVal>> thenAttemptTransform(
@NonNull Function<? super TPre, ? extends Result<? extends TVal>> attemptFunction);
}
interface RTermination<TVal, TTerm, TRet> {
@NonNull
TRet orSkip();
@NonNull
TRet orEnd(@NonNull Function<? super TTerm, ? extends TVal> valueFunction);
}
interface RConfig<TVal> {
@NonNull
RConfig<TVal> notifyIf(@NonNull Merger<? super TVal, ? super TVal, Boolean> checker);
@NonNull
RConfig<TVal> onDeactivation(@RepositoryConfig int deactivationConfig);
@NonNull
RConfig<TVal> onConcurrentUpdate(@RepositoryConfig int concurrentUpdateConfig);
@NonNull
Repository<TVal> compile();
@NonNull
<TVal2> RFrequency<TVal2, TVal> compileIntoRepositoryWithInitialValue(@NonNull TVal2 value);
}
}
我們可以看到這個(gè)狀態(tài)接口里面定義了很多狀態(tài)作煌,里面的方法真的很多掘殴,你會(huì)發(fā)現(xiàn)我們?cè)谑褂玫氖褂盟{(diào)用的方法都包含在里面。而且每個(gè)方法返回的不是repository粟誓,而是一些狀態(tài)奏寨,這就意味著我們?cè)跇?gòu)建CompiledRepository時(shí)的流程是一步步往前推進(jìn)的,這就說(shuō)明過(guò)程是不可逆的鹰服。
接下來(lái)就介紹集中關(guān)鍵的狀態(tài)病瞳,其它的狀態(tài)基本是繼承于它們:
REventSource:這個(gè)是初始狀態(tài),Repositories.repositoryWithInitialValue()這個(gè)方法的返回的結(jié)果就是REventSource获诈,表明事件源的開始仍源。
RFrequency:表示事件源發(fā)送的頻率。
RFlow:表示數(shù)據(jù)處理流舔涎,這里定義的方法都是和數(shù)據(jù)處理相關(guān)的笼踩,比如getFrom(),mergeIn()等等亡嫌。但是要注意函數(shù)的返回值嚎于,如果是RFlow說(shuō)明處理還在繼續(xù)掘而,如果是RTermination說(shuō)明處理已經(jīng)結(jié)束。
RTermination:表示最后數(shù)據(jù)處理后的終止操作于购。
RConfig:其余各種配置袍睡,比如onDeactivation():repository去活化會(huì)執(zhí)行什么操作之類。
這樣定義狀態(tài)之后肋僧,我們能很清楚的知道進(jìn)行到哪一步流程斑胜,也就更好的使用CompliedRepository(用自動(dòng)補(bǔ)全太爽了)。
初始化(Repositories.repositoryWithInitialValue(…))->
設(shè)置監(jiān)聽事件(observe())->
規(guī)定事件發(fā)送的頻率(onUpdatesPerLoop()等)->
處理數(shù)據(jù)流(各種處理函數(shù))->
結(jié)束數(shù)據(jù)流->
配置一些屬性(onDeactivation()等)->
complie()嫌吠。
這樣整個(gè)處理流程就完整了止潘。但是你可能會(huì)說(shuō),這些都只是接口辫诅,它怎么實(shí)現(xiàn)的呢凭戴?那么我們就得關(guān)注repositoryWithInitialValue()這個(gè)函數(shù):
public static <T> REventSource<T, T> repositoryWithInitialValue(@NonNull final T initialValue) {
return RepositoryCompiler.repositoryWithInitialValue(initialValue);
}
static <TVal> RepositoryCompilerStates.REventSource<TVal, TVal> repositoryWithInitialValue(
@NonNull final TVal initialValue) {
。炕矮。么夫。
return compiler.start(initialValue);
}
private RepositoryCompiler start(@NonNull final Object initialValue) {
。肤视。档痪。
return this;
}
也就是repositoryWithInitialValue(…)返回了一個(gè)RepositoryCompiler,而狀態(tài)接口的所有使用方法都在其內(nèi)部實(shí)現(xiàn)了邢滑。钞它。那compile()返回了什么呢?
public Repository compile() {
Repository repository = compileRepositoryAndReset();
recycle(this);
return repository;
}
private Repository compileRepositoryAndReset() {
checkExpect(CONFIG);
Repository repository = compiledRepository(initialValue, eventSources, frequency, directives,
notifyChecker, concurrentUpdateConfig, deactivationConfig);
殊鞭。遭垛。。
return repository;
}```
RepositoryCompiler通過(guò)compile()生成CompiledRepository操灿。這樣CompiledRepository的生成流程就完成了锯仪。是不是感覺用法很簡(jiǎn)單呀,整個(gè)流程是很清晰的趾盐,你只需要按照思路一步步往下些就好了庶喜。
最后附上UsernamesSupplierde代碼:
public class UsernamesSupplier implements Supplier<Result<List<String>>> {
public static int NUMBER_OF_USERS = 4;
private static final String TAG = UsernamesSupplier.class.getSimpleName();
private List<String> getUsernames() {
//模擬延時(shí)
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Log.e(TAG, e.toString());
return null;
}
if (NUMBER_OF_USERS < 0) {
return null;
}
String name1 = "Joe";
String name2 = "Amanda";
final List<String> usernames = new ArrayList<String>();
Random random = new Random();
for (int i = 0; i < NUMBER_OF_USERS; i++) {
int number = random.nextInt(50);
if (System.currentTimeMillis() % 2 == 0) {
usernames.add(name1 + number);
} else {
usernames.add(name2 + number);
}
}
return usernames;
}
@NonNull
@Override
public Result<List<String>> get() {
List<String> usernames = getUsernames();
if (usernames == null) {
return Result.failure();
} else {
return Result.success(getUsernames());
}
}
}
這樣通過(guò)兩種方法實(shí)現(xiàn)下拉刷新數(shù)據(jù)就完成了
小結(jié)
上面寫的有點(diǎn)亂,第一種是使用基本的observable和updatable來(lái)實(shí)現(xiàn)救鲤;第二種是使用CompliedRepository來(lái)實(shí)現(xiàn)久窟。這篇文章主要介紹了一下用法,具體的內(nèi)部邏輯小伙伴還是要自己看源碼噠1静3饪浮!
寫得有誤的地方還請(qǐng)小伙伴們多多指出5で隆O“洹芬失!