初識(shí)Agera(二)——結(jié)合Demo介紹Agera的用法

前言

在上一篇我講了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屈留。首先分析下流程:

  1. 下拉
  2. 獲取數(shù)據(jù)
  3. 更新頁(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ī)制:

  1. observable首次添加updatable->addUpdatable(Updatable)->workerhandler(handler.obtainMessage(WorkerHandler.MSG_FIRST_ADDED, this).sendToTarget();)->workerHandler.callFirstUpdatableAdded()->observable.observableActivated().
  2. 當(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更新。
  3. 當(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í)行流程了:

  1. 進(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í)候就更新完畢了。
  2. 下拉刷新觸發(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ù)的更新谍婉。
  3. 退出應(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“洹芬失!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市匾灶,隨后出現(xiàn)的幾起案子棱烂,更是在濱河造成了極大的恐慌,老刑警劉巖阶女,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颊糜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡秃踩,警方通過(guò)查閱死者的電腦和手機(jī)芭析,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吞瞪,“玉大人,你說(shuō)我怎么就攤上這事驾孔∩指眩” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵翠勉,是天一觀的道長(zhǎng)妖啥。 經(jīng)常有香客問(wèn)我,道長(zhǎng)对碌,這世上最難降的妖魔是什么荆虱? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮朽们,結(jié)果婚禮上怀读,老公的妹妹穿的比我還像新娘。我一直安慰自己骑脱,他們只是感情好菜枷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叁丧,像睡著了一般啤誊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拥娄,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天蚊锹,我揣著相機(jī)與錄音,去河邊找鬼稚瘾。 笑死牡昆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的摊欠。 我是一名探鬼主播迁杨,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼钻心,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了铅协?” 一聲冷哼從身側(cè)響起捷沸,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狐史,沒(méi)想到半個(gè)月后痒给,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骏全,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年苍柏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姜贡。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡试吁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出楼咳,到底是詐尸還是另有隱情熄捍,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布母怜,位于F島的核電站余耽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏苹熏。R本人自食惡果不足惜碟贾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望轨域。 院中可真熱鬧袱耽,春花似錦、人聲如沸干发。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)铐然。三九已至蔬崩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搀暑,已是汗流浹背沥阳。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留自点,地道東北人桐罕。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親功炮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子溅潜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容