vendredi 19 juin 2015

In which cases should I use SQLite on Android to cache data?

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