Home | History | Annotate | Download | only in contentproviderpaging
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.contentproviderpaging;
     18 
     19 import android.app.Activity;
     20 import android.app.LoaderManager;
     21 import android.content.ContentResolver;
     22 import android.content.CursorLoader;
     23 import android.content.Loader;
     24 import android.database.Cursor;
     25 import android.os.Bundle;
     26 import android.support.annotation.Nullable;
     27 import android.support.v4.app.Fragment;
     28 import android.support.v7.widget.LinearLayoutManager;
     29 import android.support.v7.widget.RecyclerView;
     30 import android.util.Log;
     31 import android.view.LayoutInflater;
     32 import android.view.View;
     33 import android.view.ViewGroup;
     34 import android.widget.Button;
     35 import android.widget.Toast;
     36 
     37 import java.util.concurrent.atomic.AtomicInteger;
     38 
     39 /**
     40  * Fragment that works as a client for accessing the DocumentsProvider
     41  * ({@link ImageProvider}.
     42  */
     43 public class ImageClientFragment extends Fragment {
     44 
     45     private static final String TAG = "ImageClientFragment";
     46 
     47     /** The number of fetched images in a single query to the DocumentsProvider. */
     48     private static final int LIMIT = 10;
     49 
     50     private ImageAdapter mAdapter;
     51 
     52     private LinearLayoutManager mLayoutManager;
     53 
     54     private final LoaderCallback mLoaderCallback = new LoaderCallback();
     55 
     56     /**
     57      * The offset position for the ContentProvider to be used as a starting position to fetch
     58      * the images from.
     59      */
     60     private AtomicInteger mOffset = new AtomicInteger(0);
     61 
     62     public static ImageClientFragment newInstance() {
     63 
     64         Bundle args = new Bundle();
     65 
     66         ImageClientFragment fragment = new ImageClientFragment();
     67         fragment.setArguments(args);
     68         return fragment;
     69     }
     70 
     71     @Nullable
     72     @Override
     73     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
     74             @Nullable Bundle savedInstanceState) {
     75         return inflater.inflate(R.layout.fragment_image_client, container, false);
     76     }
     77 
     78     @Override
     79     public void onViewCreated(View rootView, @Nullable Bundle savedInstanceState) {
     80         super.onViewCreated(rootView, savedInstanceState);
     81 
     82         final Activity activity = getActivity();
     83 
     84         RecyclerView recyclerView = (RecyclerView) activity.findViewById(R.id.recyclerview);
     85         if (mLayoutManager == null) {
     86             mLayoutManager = new LinearLayoutManager(activity);
     87         }
     88         recyclerView.setLayoutManager(mLayoutManager);
     89         if (mAdapter == null) {
     90             mAdapter = new ImageAdapter(activity);
     91         }
     92         recyclerView.setAdapter(mAdapter);
     93         recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
     94             @Override
     95             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
     96                 int lastVisiblePosition = mLayoutManager.findLastVisibleItemPosition();
     97                 if (lastVisiblePosition >= mAdapter.getFetchedItemCount()) {
     98                     Log.d(TAG,
     99                             "Fetch new images. LastVisiblePosition: " + lastVisiblePosition
    100                                     + ", NonEmptyItemCount: " + mAdapter.getFetchedItemCount());
    101 
    102                     int pageId = lastVisiblePosition / LIMIT;
    103                     // Fetch new images once the last fetched item becomes visible
    104                     activity.getLoaderManager()
    105                             .restartLoader(pageId, null, mLoaderCallback);
    106                 }
    107             }
    108         });
    109 
    110         final Button showButton = rootView.findViewById(R.id.button_show);
    111         showButton.setOnClickListener(new View.OnClickListener() {
    112             @Override
    113             public void onClick(View view) {
    114                 activity.getLoaderManager().restartLoader(0, null, mLoaderCallback);
    115                 showButton.setVisibility(View.GONE);
    116             }
    117         });
    118     }
    119 
    120     private class LoaderCallback implements LoaderManager.LoaderCallbacks<Cursor> {
    121 
    122         @Override
    123         public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    124             final Activity activity = ImageClientFragment.this.getActivity();
    125             return new CursorLoader(activity) {
    126                 @Override
    127                 public Cursor loadInBackground() {
    128                     Bundle bundle = new Bundle();
    129                     bundle.putInt(ContentResolver.QUERY_ARG_OFFSET, mOffset.intValue());
    130                     bundle.putInt(ContentResolver.QUERY_ARG_LIMIT, LIMIT);
    131                     return activity.getContentResolver()
    132                             .query(ImageContract.CONTENT_URI, null, bundle, null);
    133                 }
    134             };
    135         }
    136 
    137         @Override
    138         public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    139             Bundle extras = cursor.getExtras();
    140             int totalSize = extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE);
    141             mAdapter.setTotalSize(totalSize);
    142             int beforeCount = mAdapter.getFetchedItemCount();
    143             while (cursor.moveToNext()) {
    144                 String displayName = cursor.getString(cursor.getColumnIndex(
    145                         ImageContract.Columns.DISPLAY_NAME));
    146                 String absolutePath = cursor.getString(cursor.getColumnIndex(
    147                         ImageContract.Columns.ABSOLUTE_PATH));
    148 
    149                 ImageAdapter.ImageDocument imageDocument = new ImageAdapter.ImageDocument();
    150                 imageDocument.mAbsolutePath = absolutePath;
    151                 imageDocument.mDisplayName = displayName;
    152                 mAdapter.add(imageDocument);
    153             }
    154             int cursorCount = cursor.getCount();
    155             if (cursorCount == 0) {
    156                 return;
    157             }
    158             Activity activity = ImageClientFragment.this.getActivity();
    159             mAdapter.notifyItemRangeChanged(beforeCount, cursorCount);
    160             int offsetSnapShot = mOffset.get();
    161             String message = activity.getResources()
    162                     .getString(R.string.fetched_images_out_of, offsetSnapShot + 1,
    163                             offsetSnapShot + cursorCount, totalSize);
    164             mOffset.addAndGet(cursorCount);
    165             Toast.makeText(activity, message, Toast.LENGTH_LONG).show();
    166         }
    167 
    168         @Override
    169         public void onLoaderReset(Loader<Cursor> loader) {
    170 
    171         }
    172     }
    173 }
    174