使用分页库时,观察者将列表大小显示为零

When using Paging Library, observer showing list size as zero

我正在尝试使用较新版本的分页库。我正在使用截击从网络中获取我的数据。每当我从网络中获取数据时,都会获取数据,但是当调用转到观察者时,显示的列表大小为零。我不确定我做错了什么。

我是 android 的新手,所以对分页了解不多。自从我尝试以来已经有几天了,但仍然无法弄清楚。

我的gradle如下

apply plugin: 'com.android.application'

android {
compileSdkVersion 27
defaultConfig {
    applicationId "com.example.athansys.mypagingapplication"
    minSdkVersion 22
    targetSdkVersion 27
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.volley:volley:1.1.0'
implementation 'com.google.code.gson:gson:2.8.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

implementation "android.arch.paging:runtime:1.0.1"
implementation "android.arch.lifecycle:runtime:1.1.1"
implementation "android.arch.lifecycle:extensions:1.1.1"
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"

}

我的 MainActivity 看起来像:

package com.example.athansys.mypagingapplication;

import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.arch.paging.PagedList;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class MainActivity extends AppCompatActivity {

private MyPatientAdapter mPatientAdapter;
private RecyclerView mRecyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FilterModel viewModel = ViewModelProviders.of(this).get(FilterModel.class);
    viewModel.getData(this).observe(this, new Observer<PagedList<FilterPatientList>>() {
        @Override
        public void onChanged(@Nullable PagedList<FilterPatientList> results) {
            mPatientAdapter.submitList(results);
            //mPatientAdapter.setList(results);
            mPatientAdapter.notifyDataSetChanged();
            mRecyclerView.setAdapter(mPatientAdapter);
        }
    });
}

private void setAdapter() {

    mRecyclerView = findViewById(R.id.my_patient_recycler_view);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
    mPatientAdapter = new MyPatientAdapter();
    mRecyclerView.setLayoutManager(layoutManager);
    mRecyclerView.setAdapter(mPatientAdapter);

}
}

FilterModel class如下:

package com.example.athansys.mypagingapplication;


import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.ViewModel;
import android.arch.paging.LivePagedListBuilder;
import android.arch.paging.PagedList;
import android.content.Context;
import android.util.Log;

public class FilterModel extends ViewModel {
private LiveData<PagedList<FilterPatientList>> listLiveData;

LiveData<PagedList<FilterPatientList>> getData(Context context) {
    if (listLiveData == null) {

        PagedList.Config pagedListConfig =
                (new PagedList.Config.Builder()).setEnablePlaceholders(false)
                        .setPrefetchDistance(5)
                        .setPageSize(1).build();

        listLiveData = new LivePagedListBuilder<>
                (new MyPatientPagedListProvider(context)
                        .getAll()
                        , pagedListConfig).
                build();

    }
    return listLiveData;
}
}

MyProvider class 是:

    package com.example.athansys.mypagingapplication;

import android.arch.paging.DataSource;
import android.arch.paging.LivePagedListProvider;
import android.content.Context;
import android.util.Log;

import java.util.List;


public class MyPatientPagedListProvider {

Context mBaseContext;

public MyPatientPagedListProvider(Context context) {
    mBaseContext = context;
    dataClass.getContextInstance(context);
}

private static final String TAG = MyPatientPagedListProvider.class.getName();

MyPatientData dataClass = new MyPatientData() {
    @Override
    public List<FilterPatientList> convertToItems(List<FilterPatientList> result, int size) {
        return result;
    }
};

public LivePagedListProvider<Integer, FilterPatientList> getAll() {
    return new LivePagedListProvider<Integer, FilterPatientList>() {
        @Override
        protected DataSource<Integer, FilterPatientList> createDataSource() {
            return dataClass;
        }
    };
}
}

MyDataSource如下:

    package com.example.athansys.mypagingapplication;

import android.arch.paging.TiledDataSource;
import android.content.Context;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class MyPatientData extends TiledDataSource<FilterPatientList> {

private Context mContext;
private List<FilterPatientList> patientList;

@Override
public int countItems() {
    return 10;
}

@Override
public List<FilterPatientList> loadRange(int startPosition, int count) {
    String url = "My URl";
    return postStringRequestForMyPatient(url);
}

public List<FilterPatientList> postStringRequestForMyPatient(String url) {
    StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            JSONObject jsonObject = null;
            try {
                jsonObject = new JSONObject(response);
                String data = jsonObject.getString("patientsfordoctor");
                mPatientsForDoctor = new Gson().fromJson(data, PatientsForDoctor.class);
                mPatientList = new ArrayList<>();

                mPatientList.addAll(mPatientsForDoctor.getPatientList());

            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    }) {

        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            return super.getParams();
        }

        @Override
        public String getBodyContentType() {
            return super.getBodyContentType();
        }

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            return new HashMap<>();
        }
    };
    stringRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    Volley.newRequestQueue(mContext).add(stringRequest);
}

void getContextInstance(Context context) {
    mContext = context;
}

public abstract List<FilterPatientList> convertToItems(List<FilterPatientList> result, int size);
}

我的适配器class

    package com.example.athansys.mypagingapplication;
import android.arch.paging.PagedListAdapter;
import android.support.annotation.NonNull;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MyPatientAdapter extends PagedListAdapter<FilterPatientList, MyPatientAdapter.PatientViewHolder> {

protected MyPatientAdapter() {
    super(FilterPatientList.DIFF_CALLBACK);
}

@NonNull
@Override
public PatientViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return null;
}

@Override
public void onBindViewHolder(@NonNull PatientViewHolder holder, int position) {

}


class PatientViewHolder extends RecyclerView.ViewHolder {
    TextView patientName, patientPhoneNumber, genderAge;

    PatientViewHolder(View itemView) {
        super(itemView);
    }
}
}

我的 POJO(型号 CLASSES 如下)

FilterPatientListclass:

    package com.example.athansys.mypagingapplication;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v7.util.DiffUtil;

import com.google.gson.annotations.SerializedName;

public class FilterPatientList implements Parcelable {

private long patientId;

private Patient patientDetails;

protected FilterPatientList(Parcel in) {
    patientId = in.readLong();
    patientDetails = in.readParcelable(Patient.class.getClassLoader());
}

public static final Creator<FilterPatientList> CREATOR = new Creator<FilterPatientList>() {
    @Override
    public FilterPatientList createFromParcel(Parcel in) {
        return new FilterPatientList(in);
    }

    @Override
    public FilterPatientList[] newArray(int size) {
        return new FilterPatientList[size];
    }
};

public long getPatientId() {
    return patientId;
}

public void setPatientId(long patientId) {
    this.patientId = patientId;
}

public Patient getPatientDetails() {
    return patientDetails;
}

public void setPatientDetails(Patient patientDetails) {
    this.patientDetails = patientDetails;
}


@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeLong(patientId);
    dest.writeParcelable(patientDetails, flags);
}

public static final DiffUtil.ItemCallback<FilterPatientList> DIFF_CALLBACK = new DiffUtil.ItemCallback<FilterPatientList>() {
    @Override
    public boolean areItemsTheSame(FilterPatientList oldItem, FilterPatientList newItem) {
        return false;
    }

    @Override
    public boolean areContentsTheSame(FilterPatientList oldItem, FilterPatientList newItem) {
        return false;
    }
};
}

患者CLASS:

   package com.example.athansys.mypagingapplication;
import android.os.Parcel;
import android.os.Parcelable;

import com.google.gson.annotations.SerializedName;

public class Patient implements Parcelable{

private long localPatientId;


private long apptDoctorId;

private long patientId;
private boolean isLocalPatient;

private String firstName;
private String lastName;
private String phoneNumber;
private String email;
private String dob;
private int age;
private int height;
private int weight;
private String patientSex;
private String patientSystemRegistrationDate;
private int bloodGroup;


protected Patient(Parcel in) {
    localPatientId = in.readLong();
    apptDoctorId = in.readLong();
    patientId = in.readLong();
    isLocalPatient = in.readByte() != 0;
    firstName = in.readString();
    lastName = in.readString();
    phoneNumber = in.readString();
    email = in.readString();
    dob = in.readString();
    age = in.readInt();
    height = in.readInt();
    weight = in.readInt();
    patientSex = in.readString();
    patientSystemRegistrationDate = in.readString();
    bloodGroup = in.readInt();
}

public static final Creator<Patient> CREATOR = new Creator<Patient>() {
    @Override
    public Patient createFromParcel(Parcel in) {
        return new Patient(in);
    }

    @Override
    public Patient[] newArray(int size) {
        return new Patient[size];
    }
};

public long getLocalPatientId() {
    return localPatientId;
}

public void setLocalPatientId(long localPatientId) {
    this.localPatientId = localPatientId;
}

public long getApptDoctorId() {
    return apptDoctorId;
}

public void setApptDoctorId(long apptDoctorId) {
    this.apptDoctorId = apptDoctorId;
}

public long getPatientId() {
    return patientId;
}

public void setPatientId(long patientId) {
    this.patientId = patientId;
}

public boolean isLocalPatient() {
    return isLocalPatient;
}

public void setLocalPatient(boolean localPatient) {
    isLocalPatient = localPatient;
}

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public String getPhoneNumber() {
    return phoneNumber;
}

public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getDob() {
    return dob;
}

public void setDob(String dob) {
    this.dob = dob;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public int getHeight() {
    return height;
}

public void setHeight(int height) {
    this.height = height;
}

public int getWeight() {
    return weight;
}

public void setWeight(int weight) {
    this.weight = weight;
}

public String getPatientSex() {
    return patientSex;
}

public void setPatientSex(String patientSex) {
    this.patientSex = patientSex;
}

public String getPatientSystemRegistrationDate() {
    return patientSystemRegistrationDate;
}

public void setPatientSystemRegistrationDate(String patientSystemRegistrationDate) {
    this.patientSystemRegistrationDate = patientSystemRegistrationDate;
}

public int getBloodGroup() {
    return bloodGroup;
}

public void setBloodGroup(int bloodGroup) {
    this.bloodGroup = bloodGroup;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeLong(localPatientId);
    dest.writeLong(apptDoctorId);
    dest.writeLong(patientId);
    dest.writeByte((byte) (isLocalPatient ? 1 : 0));
    dest.writeString(firstName);
    dest.writeString(lastName);
    dest.writeString(phoneNumber);
    dest.writeString(email);
    dest.writeString(dob);
    dest.writeInt(age);
    dest.writeInt(height);
    dest.writeInt(weight);
    dest.writeString(patientSex);
    dest.writeString(patientSystemRegistrationDate);
    dest.writeInt(bloodGroup);
}
}

当我在数据源 class(MyPatientData) 中从网络接收数据时,调用会自动转到主 activity 中的观察者。此处显示的列表大小为零,而从网络获取的列表大小为 10 个项目。

你能帮帮我吗?我真的被困了好几天不知道下一步该怎么做。 非常感谢。 :)

这是分页的简单解决方案。

第一次 private void jsonRequestList(int pageCount) { 将用 pageCount=1 调用,下一次用 2,3,4...

递增

内部 private void jsonRequestList(int pageCount) { 方法 (JSON REQUEST) 第一次 if (!isScrollCalled) { 将被调用,下一次 else 块将被调用。

Activity/Fragment :

     private boolean loading = false;
     private boolean isScrollCalled;
     int isLastPage = 10;
     int pageCount = 1;

     //Paigination
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                int lastvisibleitemposition = linearLayoutManager.findLastVisibleItemPosition();

                if (lastvisibleitemposition == adapter.getItemCount() - 1) {

                    if (!loading && pageCount != isLastPage) {
                        loading = true;
                        jsonRequestList(++pageCount);
                        isScrollCalled = Boolean.TRUE;
                    }


                }
            }
        });


 private void jsonRequestList(int pageCount) {
  //Json Request

  if (!isScrollCalled) {
          adapter = new FlowerListAdapter(FlowerListActivity.this, list);
          recyclerView.setAdapter(adapter);
          adapter.notifyDataSetChanged();
               //  Log.e("LIST_SIZE", "" + list.size());
          } else {
          adapter.updateList(list);
          //Log.e("LIST_SIZE", "" + list.size());

        }

       loading = false;
}

回收器适配器:

 ArrayList<YourModelClass> list;
 Context context;

 //Pagination
public void updateList(ArrayList<YourModelClass> list) {
    this.list.addAll(list);
    this.notifyDataSetChanged();
}

您可以在 LivePagedListBuilder 中实现 BoundaryCallback。它包含方法 onZeroItemsLoaded。

listLiveData = new LivePagedListBuilder<>
                (new MyPatientPagedListProvider(context)
                        .getAll()
                        , pagedListConfig)
                        .setBoundaryCallback(new PagedList.BoundaryCallback() {
                    @Override
                    public void onZeroItemsLoaded() {
                        super.onZeroItemsLoaded();
 // do smth here. For example, post boolean value to MutableLiveData to notify activity //that result is empty
                    }
                })
                .build();

要获取插入项目的大小或 RecyclerView 的大小,我们需要向我们的 RecyclerView 注册一个 AdapterDataObserver

1) 创建一个 AdapterDataObserver 并覆盖你想要的函数。

public class SearchListAdapterDataObserver extends RecyclerView.AdapterDataObserver {

    private RecyclerView mRecyclerView;
    private ChangeListener mChangeListener;

    public SearchListAdapterDataObserver(RecyclerView view, ChangeListener changeListener){
        this.mRecyclerView = view;
        this.mChangeListener = changeListener;
    }

    @Override
    public void onChanged() {
        super.onChanged();
        sendItemCount();
    }

    private void sendItemCount() {
        if(mRecyclerView.getAdapter() != null) {
            mChangeListener.onChanged(getSize());
        }
    }

    @Override
    public void onItemRangeInserted(int positionStart, int itemCount) {
        super.onItemRangeInserted(positionStart, itemCount);
        sendItemCount();
    }

    @Override
    public void onItemRangeChanged(int positionStart, int itemCount) {
        super.onItemRangeChanged(positionStart, itemCount);
        sendItemCount();
    }

    @Override
    public void onItemRangeRemoved(int positionStart, int itemCount) {
        super.onItemRangeRemoved(positionStart, itemCount);
        sendItemCount();
    }

    public int getSize() {
        if(mRecyclerView.getAdapter() != null) {
            return mRecyclerView.getAdapter().getItemCount();
        }
        return 0;
    }

    public interface ChangeListener {
        void onChanged(int size);
    }
}

2) 将其注册到您的适配器并收听更改。

if(mViewModel.getSearchPaginatedAdapter() != null){
        mViewModel.getSearchPaginatedAdapter().registerAdapterDataObserver
                (new SearchListAdapterDataObserver(mRecyclerView, new SearchListAdapterDataObserver.ChangeListener() {
            @Override
            public void onChanged(int size) {
                onListChanges(size);
            }
        }));
    }

修改@Mike Makhovyk,这是我最终想出的办法

在您的 ViewModel 上

创建可变布尔值

private MutableLiveData<Boolean> emptyListMutableLiveData = new MutableLiveData<>();

listLiveData = new LivePagedListBuilder<>
                (new MyPatientPagedListProvider(context)
                        .getAll()
                        , pagedListConfig)
                        .setBoundaryCallback(new PagedList.BoundaryCallback() {
                    @Override
                    public void onZeroItemsLoaded() {
                        super.onZeroItemsLoaded();
                        emptyListMutableLiveData.setValue(true)
                    }

                    @Override
                    public void onItemAtFrontLoaded(@NonNull Complaint itemAtFront) {
                        super.onItemAtFrontLoaded(itemAtFront);
                        emptyListMutableLiveData.setValue(false);
                    }

                })
                .build();

创建一个方法,return te livedata

public LiveData<Boolean> isEmptyList() {
        return emptyListMutableLiveData;
    }

在您的 fragment/activity 上,您可以观察布尔结果,然后更新您的 UI