按照如下步驟開發
- Step1 數據層:數據倉庫實現
public class HotContentItem {
public String id;
public String name;
public String desc;
public long timeStamp;
}
複製代碼
public class HotContentNetRepository {
public Either<? extends Failure, List<HotContentItem>> refreshNew() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
Either<? extends Failure, List<HotContentItem>> result;
Random random = new Random();
boolean success = random.nextInt(10) > 3;
if (success) {
result = Either.right((mockItemList(0)));
} else if (random.nextInt(10) > 3) {
result = Either.right(Collections.<HotContentItem>emptyList());
} else {
result = Either.left(new NetworkFailure());
}
return result;
}
}
複製代碼
- Step2 邏輯層:數據倉庫選擇及使用
- 省略列這一步,按照業務需求實現不一樣的數據倉庫組合使用
- Step3 邏輯層:實現UseCase(示例代碼:刷新數據)
public class HotContentRefreshNew extends BaseUseCase<List<HotContentItem>, Void> {
private HotContentNetRepository mNetRepository;
public HotContentRefreshNew( MutableLiveData<List<HotContentItem>> data, MutableLiveData<Failure> failure) {
super(data, failure);
mNetRepository = new HotContentNetRepository();
}
@Override
protected Either<? extends Failure, List<HotContentItem>> loadData(Void aVoid) {
Either<? extends Failure, List<HotContentItem>> result = mNetRepository.refreshNew();
if (result.isRight() && CollectionUtil.isEmpty(result.right())) {
Failure failure = new RefreshNewFailure(RefreshNewFailure.CODE_DATA_EMPTY, "Data is empty!");
result = Either.left(failure);
}
return result;
}
@Override
protected Failure processFailure(Failure failure) {
...
}
}
複製代碼
- Step4 展現層:UI框架選擇
- 示例界面是做爲一個TabLayout的一個Page頁,所以這裏選擇"具有生命週期View"做爲的UI框架,這是個自定的View,實現了LifecycleOwner接口(參考了LifecycleActivity和LifecycleFragment的實現邏輯)
public abstract class BaseLifecycleView extends FrameLayout implements LifecycleOwner {
private final LifecycleRegistry mRegistry = new LifecycleRegistry(this);
private ViewModelStore mViewModelStore = new ViewModelStore();
public BaseLifecycleView(@NonNull Context context) {
super(context);
}
protected abstract void onCreate();
protected abstract void onDestroy();
@Override
public Lifecycle getLifecycle() {
return mRegistry;
}
@Override
@CallSuper
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mRegistry.handleLifecycleEvent(Event.ON_CREATE);
onCreate();
if (getVisibility() == View.VISIBLE) {
mRegistry.handleLifecycleEvent(Event.ON_START);
}
}
@Override
@CallSuper
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mRegistry.handleLifecycleEvent(Event.ON_DESTROY);
mViewModelStore.clear();
onDestroy();
}
@Override
@CallSuper
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
Event event = visibility == View.VISIBLE ? Event.ON_RESUME : Event.ON_PAUSE;
mRegistry.handleLifecycleEvent(event);
}
@Override
@CallSuper
public void onStartTemporaryDetach() {
super.onStartTemporaryDetach();
State state = mRegistry.getCurrentState();
if (state == State.RESUMED) {
mRegistry.handleLifecycleEvent(Event.ON_STOP);
}
}
@Override
@CallSuper
public void onFinishTemporaryDetach() {
super.onFinishTemporaryDetach();
State state = mRegistry.getCurrentState();
if (state == State.CREATED) {
mRegistry.handleLifecycleEvent(Event.ON_START);
}
}
protected <T extends ViewModel> T getViewModel(@NonNull ViewModelProvider.NewInstanceFactory modelFactory, @NonNull Class<T> modelClass) {
return new ViewModelProvider(mViewModelStore, modelFactory).get(modelClass);
}
}
複製代碼
- Step5 展現層:定義本身的LiveData和ViewModel
public class HotContentViewModel extends BaseViewModel<List<HotContentItem>> {
private HotContentRefreshNew mRefreshNew;
public HotContentViewModel() {
refreshNew();
}
public void refreshNew() {
AssertUtil.mustInUiThread();
if (mRefreshNew == null) {
mRefreshNew = new HotContentRefreshNew(getMutableLiveData(), getMutableFailure());
}
mRefreshNew.executeOnAsyncThread(null);
}
...
}
複製代碼
public class HotContentView extends BaseLifecycleView {
private HotContentViewModel mViewModel;
private SwipeRefreshLayout mSwipeRefreshLayout;
private AutoLoadMoreRecycleView mRecyclerView;
private HotContentAdapter mContentAdapter;
public HotContentView(@NonNull Context context) {
super(context);
視圖對象初始化
...
mRecyclerView.setLoadMoreListener(new LoadMoreListener() {
@Override
public void onLoadMore() {
HotContentItem lastOne = CollectionUtil.lastOne(mViewModel.getData().getValue());
if (lastOne == null) {
mRecyclerView.completeLoadMore("No more data");
} else {
mViewModel.loadHistory(lastOne);
}
}
});
...
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mViewModel.refreshNew();
}
});
}
@Override
protected void onCreate() {
mViewModel = getViewModel(new NewInstanceFactory(), HotContentViewModel.class);
mViewModel.getData().observe(this, new Observer<List<HotContentItem>>() {
@Override
public void onChanged(@Nullable List<HotContentItem> hotContentItems) {
mContentAdapter.setItemList(hotContentItems);
mSwipeRefreshLayout.setRefreshing(false);
...
}
});
...
}
@Override
protected void onDestroy() {
}
}
複製代碼