So, I write an client for video platform.
Let's see at one of features of my app: Fetching video.
Now, I use RxJava + Retrofit to fetch video and display it.
Below is a code without caching:
Retrofit api:
@GET("/api_v3/?service=media&action=list&pager%3AobjectType=KalturaFilterPager&pager%3ApageSize=500&pager:pageIndex=1")
Observable<KalturaVideoResponse> getVideoListObservable();
And usage in Activity:
API.getVideoListObservable()
.doOnError(t -> t.printStackTrace()) //handle error
.map(r -> r.getObjects()) //get business objects from response
.doOnNext(l -> VideoActivity.this.runOnUiThread(() -> fragment.updateVideoList(l))) //update UI
.doOnNext(l -> kalturaVideoList.addAll(l)) //save objects into memory
.subscribeOn(Schedulers.io()) //do it in background thread
.observeOn(AndroidSchedulers.mainThread()) //handle result in UI thread
.subscribe();
Advantages:
- Very simple code
- Simple handling exceptions
- Simple data manipulations (Using RxJava operators)
Disadvantages:
- At every sreen rotation will be new HttpRequest
- A lot of anonymouse classes
- If I will be do it frequently, I get OOM on not top devices. For example, on Alcatel one touch 4033d
And other example. Using SyncAdapter + ContentProvider. I will not add code of SyncAdapter configuration, I just add code, which responsible for video synchroniztion
private void updateVideoList(){
KalturaVideoResponse videoList = API.getVideoList();
getContext().getContentResolver().delete(KalturaVideoColumns.CONTENT_URI, null, null);
for(KalturaVideo video : videoList.getObjects()){
final KalturaVideoContentValues values = new KalturaVideoContentValues();
values
.putCategories(video.getCategories())
.putCategoriesIds(video.getCategoriesIds())
.putDataUrl(video.getDataUrl())
.putDescription(video.getDescription())
.putName(video.getName())
.putDownloadUrl(video.getDownloadUrl())
.putDuration(video.getDuration())
.putKalturaId(video.getId())
.putThumbnailUrl(video.getThumbnailUrl());
getContext().getContentResolver().insert(KalturaVideoColumns.CONTENT_URI, values.values());
}
} getContext().getContentResolver().insert(KalturaVideoColumns.CONTENT_URI, values.values());
}
}
This function called every time, when syncadapter synchronizing. At my configuration it does it every 30 min.
And getting data at activity(Using CursorLoader):
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
final String sortOrder = KalturaVideoColumns._ID + " DESC";
return new CursorLoader(
getActivity().getApplicationContext(),
KalturaVideoColumns.CONTENT_URI,
null,
null,
null,
sortOrder);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
KalturaVideoCursor videoCursor = new KalturaVideoCursor(cursor);
if(videoCursor.moveToFirst()){
videoAdapter = new VideoAdapter(getActivity(), cursor, true);
viewHolder.videoList.setAdapter(videoAdapter);
viewHolder.videoList.setOnItemClickListener(onItemClickListener);
}
}
At this code I just fetching videos, which was cached by SyncAdapter and display it using VideoAdapter.
Advantages:
- I don't a lot of HttpRequests, I do it every 30 mins.
- Simple Activity lifecycle handling
- Very fast loading and displaying data
Disadvantages:
There are 2 fatal disadvantage.
-
If video was edited or deleted, I don't know about it.
-
If I do frequent synchronization(for example every 3 min), my app works very slow...
How can I fix this problem?
When I start learning android, I found very beautiful android course on Udacity. In this course I developed Sunshine app. And in this app used syncadapter, which cached data in SQLite. In Sunshine app was data about weather, which updates not frequently.
But I need frequent synchronization to see, if changes was occured. Do I need to improve my caching/synchronization code, or I should do request every time when I need data?
Aucun commentaire:
Enregistrer un commentaire