【问题标题】:Android pagination for search query用于搜索查询的 Android 分页
【发布时间】:2020-11-06 05:27:56
【问题描述】:

我是 android 开发新手,正在尝试为我的应用程序构建 UI。 该应用程序与 REST 后端集成,后者接受搜索查询和项目列表作为响应。

interface RetrofitEndpoint {

    @GET("paged/list/endpoint")
    Call<PagedList<Object>> getPagedList(@Query("query") String query, @Query("pageSize") int pageSize, Query("pageOffset") int pageOffset);
}

UI 一次向用户显示一项。

我正在将列表加载到回收站视图中

public class SomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<Object> list;


    // .. other overridden members

    public void setList(List<Object> list) {
        this.list = list;
        notifyDataSetChanged();
    }

    public void addAll(List<Object> newList) {
        int lastIndex = list.size() - 1;
        list.addAll(newList);
        notifyItemRangeInserted(lastIndex, newList.size());
    }
}

我无法弄清楚的部分是当我到达回收站视图的末尾(或之前以避免延迟)时如何加载更多数据,是否有任何库/API 可以做到这一点?

【问题讨论】:

  • 你想只用网络回答还是用数据库+网络回答?我最近都做了,所以我可以帮助你......
  • 你能分享两个吗?

标签: android android-recyclerview pagination retrofit2 android-paging


【解决方案1】:

您可以将onScrollStateChanged 监听器添加到您的 RecyclerView 以检测您的 RecyclerView 的当前位置,然后添加您的逻辑以获取您想要的特定条件

【讨论】:

    【解决方案2】:

    要使分页列表正常工作,它需要在您的应用中添加更多内容。此实现使用视图模型、实时数据和房间持久性,因此它可以离线工作。

    你的 build.gradle:

    // ViewModel
    def lifecycle_version = "2.2.0"
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    
    def room_version = "2.2.5"
    
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"
    
    def paging_version = "2.1.2"
    implementation "androidx.paging:paging-runtime:$paging_version"    
    

    改造 api:

    interface RetrofitEndpoint {
    
        @GET("paged/list/endpoint")
        Call<List<YourObject>> getYourObjectList(@Query("query") String query, @Query("pageSize") int pageSize, Query("pageOffset") int pageOffset);
    }
    

    你的对象:

    @Entity(tableName = "your_object")
    public class YourObject implements Serializable {
    
    @PrimaryKey(autoGenerate = true)
    private int db_id;
    ...
    

    道:

    @Dao
    public interface YourObjectDao{
    
        /**
         * Get your objects from the table.
         * -------------------------------
         * We  get update every time the database update.
         * 
         *
         * @return your object from the table
         */
    
        @Insert
        void insert(YourObject yourObject);
    
        @Insert
        void insertList(List<YourObject> yourObjectList);
    
        @Query("SELECT * FROM your_object")
        DataSource.Factory<Integer, YourObject> getAllResults();
    
        @Query("DELETE FROM your_object")
        void deleteAll();
    
    }
    

    数据库:

    @androidx.room.Database(entities = {YourObject.class}, version = 1)
    public abstract class Database extends RoomDatabase {
    
    private static Database instance;
    public abstract YourObjectDao get_your_object_dao();
    
    public static synchronized Database getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(context.getApplicationContext(),
                    Database.class, DATABASE_NAME)
                    .fallbackToDestructiveMigration()
                    .addCallback(roomCallback)
                    .build();
        }
        return instance;
    }
    }
    

    YourObjectBoundaryCallback:

    public class YourObjectBoundaryCallback extends PagedList.BoundaryCallback<YourObject> {
        private AppExecutors executors;
        private Database database;
        private YourObjectDao dao;
        private Integer page_number;
    
        public YourObjectBoundaryCallback (Application application, AppExecutors executors) {
            //super();
            this.executors = executors;
            database = Database.getInstance(application);
            dao = database.get_your_object_dao();
            page_number=1;
        }
    
        @Override
        public void onZeroItemsLoaded() {
            super.onZeroItemsLoaded();
            Log.d("log", "yourObjects onzeroitemsloaded");
            fetchYourObjects(page_number);
        }
    
        @Override
        public void onItemAtFrontLoaded(@NonNull YourObject itemAtFront) {
            super.onItemAtFrontLoaded(itemAtFront);
            Log.d("log", "yourObjects onItemAtFrontLoaded");
        }
    
        @Override
        public void onItemAtEndLoaded(@NonNull YourObject itemAtEnd) {
            super.onItemAtEndLoaded(itemAtEnd);
            Log.d("log", "yourObjects onItemAtEndLoaded");
            page_number=page_number+1;
            fetchYourObjects(page_number);
        }
    
        public void fetchYourObjects(int pageNumber) {
            RetrofitApi retrofitApi = RetrofitInstance.getRetrofitEndpoint();
            Call<List<YourObject>> call = retrofitApi.getYourObjectList(query, pageSize,pageNumber);
            call.enqueue(new Callback<List<YourObject>>() {
                @Override
                public void onResponse(Call<List<YourObject>> call, Response<List<YourObject>> response) {
                    if (!response.isSuccessful()) {
                        Log.d("log", "YourObjects Response unsuccesful: " + response.code());
                        return;
                    }
                    Log.d("log", "YourObjects Response ok: " + response.code());
                    List<YourObject> yourObjectsList = response.body();
                    insertListToDb(yourObjectsList );
                }
    
                @Override
                public void onFailure(Call<List<YourObject>> call, Throwable t) {
                    Log.d("log", "yourObjects onFailure: " + t.getMessage());
                }
            });
        }
    
    
        public void insertListToDb(List<YourObject> list) {
            Runnable runnable = () -> {
                dao.insertList(list);
            };
            Runnable diskRunnable = () -> database.runInTransaction(runnable);
            executors.diskIO().execute(diskRunnable);
        }
        }
    

    YourObjects 存储库:

    public class YourObjectsRepository {
    private LiveData<PagedList<YourObject>> yourObjectsPagedList;
    private YourObjectBoundaryCallback yourObjectsBoundaryCallback;
    private AppExecutors executors;
    
    
    public YourObjectsRepository (Application application, AppExecutors executors) {
        this.executors = executors;
        Database database = Database.getInstance(application);
        YourObjectDao dao = database.get_your_object_dao();
        yourObjectsBoundaryCallback= new YourObjectBoundaryCallback (application, executors);
        createYourObjectsPagedList(dao );
    
    }
    
    //this is configuration for your paged list, adjust per your requirements
    private PagedList.Config getPagedListConfig(){
        return  (new PagedList.Config.Builder())
                .setEnablePlaceholders(false)
                .setPrefetchDistance(40)
                .setInitialLoadSizeHint(60)
                .setPageSize(20).build();
    }
    
    private void createYourObjectsPagedList(YourObjectDao dao){
        yourObjectsPagedList= new LivePagedListBuilder<>(dao.getAllResults(), getPagedListConfig())
          .setBoundaryCallback(yourObjectsBoundaryCallback).setFetchExecutor(executors.networkIO())
                .build();
    }
    
    public LiveData<PagedList<YourObject>> getYourObjectsPagedList() {
        return yourObjectsPagedList;
    }
    }
    

    YourObjectsViewModel:

    public class YourObjectsViewModel extends AndroidViewModel {
    
        private YourObjectsRepository repo;
    
        public YourObjectsViewModel (@NonNull Application application) {
            super(application);
            AppExecutors  executors = new AppExecutors();
            repo= new YourObjectsRepository (application, executors);
        }
    
    
        public LiveData<PagedList<YourObject>> getYourObjectsPagedList() {
            return repo.getYourObjectsPagedList();
        }
    }
    

    AppExecutors:

    public class AppExecutors {
    private final Executor diskIO;
    private final Executor networkIO;
    private final Executor mainThread;
    private final Executor others;
    private final Executor paging;
    
        public AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread, Executor others, Executor paging) {
            this.diskIO = diskIO;
            this.networkIO = networkIO;
            this.mainThread = mainThread;
            this.others = others;
            this.paging = paging;
        }
        public AppExecutors() {
            this(Executors.newSingleThreadExecutor(), Executors.newFixedThreadPool(3),
                    new MainThreadExecutor(), Executors.newSingleThreadExecutor(),
                    Executors.newFixedThreadPool(4));
        }
    
        public Executor diskIO() {
            return diskIO;
        }
    
        public Executor networkIO() {
            return networkIO;
        }
    
        public Executor mainThread() {
            return mainThread;
        }
    
        public Executor others() {
            return others;
        }
    
        public Executor paging() {
            return paging;
        }
    
        private static class MainThreadExecutor implements Executor {
            private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
            @Override
            public void execute(@NonNull Runnable command) {
                mainThreadHandler.post(command);
            }
        }
    }
    

    在您的活动/片段中:

    yourObjectsViewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())).get(YourObjectsViewModel.class);
    yourObjectsViewModel.getYourObjectPagedList().observe(getViewLifecycleOwner(), new Observer<PagedList<TopRatedMovie>>() {
            @Override
            public void onChanged(PagedList<YourObject> results) {
                Log.d("log", "  onChanged list size: " + results.size());
                yourAdapter.submitList(results);
               
            }
        });
    

    在您的适配器中:

     public class YourPagedListAdapter extends PagedListAdapter<YourObject, 
     RecyclerView.ViewHolder> {
    

    如果您有任何问题,请随时提出。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多