快速滚动并在onBindViewHolder上调用API后,RecyclerView崩溃

时间:2019-02-10 04:11:48

标签: java android android-recyclerview

public class FragmentPatientsByVital extends Fragment {

    private RecyclerView mRecyclerView;
    private ArrayList<Patient> mList;
    private AdapterVitalPatient mAdapter;
    private MultiStateToggleButton mMultiStateToggleButton;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_patient_by_vital, container, false);
        initUi(v);

        if (mList != null)
            updateList(mList);

        return v;
    }

    private void initUi(View v) {
        mRecyclerView = (RecyclerView) v.findViewById(R.id.recycler_view);
        mMultiStateToggleButton = (MultiStateToggleButton) v.findViewById(R.id.mstb_multi_id);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        mMultiStateToggleButton.setOnValueChangedListener(new ToggleButton.OnValueChangedListener() {
            @Override
            public void onValueChanged(int position) {
                mAdapter.filterBy(position);
            }
        });
    }

    public void updateList(ArrayList<Patient> mList) {
        if (mList == null) return;
        this.mList = mList;

        if (mAdapter == null)
            mAdapter = new AdapterVitalPatient(mList);

        mRecyclerView.setAdapter(mAdapter);
    }

    public static FragmentPatientsByVital newIntance() {
        FragmentPatientsByVital f = new FragmentPatientsByVital();
        return f;
    }
}    

适配器

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

    private ArrayList<Patient> mList;

    public AdapterVitalPatient(ArrayList<Patient> mList) {
        this.mList = mList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(InjectUtils.getInflator().inflate(R.layout.adapter_vital_patient, parent, false));
    }

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

        Patient p = mList.get(position);
        holder.mNameTextView.setText(p.getName());

        if (mList.get(position).getSummary() != null) {
            holder.updateRecords(mList.get(position).getSummary());
        } else {
            try {
                holder.callApi(p.getEmail(), position);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    public void filterBy(int position) {
        switch (position) {
            case 0:             //!--- Any

                break;

            case 1:             //!--- Normal

                break;

            case 2:             //!--- High
                break;

            case 3:             //!--- Low
                break;

        }
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView mNameTextView;
        private final ProgressBar mProgressBar;
        private final GridLayout mTableLayout;

        public ViewHolder(View itemView) {
            super(itemView);
            mNameTextView = (TextView) itemView.findViewById(R.id.textview_title);
            mProgressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
            mTableLayout = (GridLayout) itemView.findViewById(R.id.table_layout);
        }

        public void callApi(String email, final int pos) {

            try {
                RahaDelegates api = InjectUtils.getNetworkObj().create(RahaDelegates.class);
                Call<String> call = api.getLatestVitals(String.format(RahaDelegates.GET_LATEST_VITALS, email));
                InjectUtils.getNetworkClient().callApi(call, new ApiInterface() {

                    @Override
                    public void onResponse(boolean result, String completeResponse) {

                        Type token = new TypeToken<ArrayList<Vital>>() {
                        }.getType();
                        mList.get(getAdapterPosition()).setSummary((ArrayList<Vital>) InjectUtils.getGsonObj().fromJson(completeResponse, token));
                        updateRecords(mList.get(pos).getSummary());
                        mProgressBar.setVisibility(View.GONE);
                    }

                    @Override
                    public void onFailure(String message) {
                        mProgressBar.setVisibility(View.GONE);
                    }
                });
            } catch (Exception e){
                e.printStackTrace();
            }
        }

        public void updateRecords(ArrayList<Vital> details) {
            mTableLayout.setVisibility(View.VISIBLE);
            mProgressBar.setVisibility(View.GONE);
            mTableLayout.removeAllViews();

                for (int i = 0; i < details.size(); i++) {
                    Log.e("List Size", String.valueOf(details.size()));
                    Vital v = details.get(i);
                    if (!v.getVitalName().toLowerCase().contains("lungreco") && !v.getVitalName().toLowerCase().contains("kickco")) {
                        View view = InjectUtils.getInflator().inflate(R.layout.adapter_home_vital_patient, mTableLayout, false);
                        mTableLayout.addView(view);
                        TextView name = (TextView) view.findViewById(R.id.vital_name);
                        TextView value = (TextView) view.findViewById(R.id.vital_value);
                        name.setText(v.getVitalName());

                        if (v.getVitalName().toLowerCase().contains("bodyc")) {
                            value.setText(v.getFat() + "/" + v.getMuscale() + " " + v.getUnit());
                        } else if (v.getVitalName().toLowerCase().contains("temp")) {
                            if (v.getValue() != null) {
                                value.setText(Math.round(Float.valueOf(v.getValue())) + " " + v.getUnit());
                            }
                        } else if (v.getVitalName().toLowerCase().contains("heartra")) {
                            value.setText(v.getValue());
                        } else if (v.getVitalName().toLowerCase().contains("etalbe")) {
                            value.setText(v.getValue() + " " + v.getUnit());
                        } else if (v.getVitalName().toLowerCase().contains("bloodpres")) {
                            value.setText(v.getSystolic() + "/" + v.getDiastolic() + " " + v.getUnit());
                        } else if (v.getVitalName().toLowerCase().contains("loodoxy")) {
                            value.setText(v.getValue() + " " + v.getUnit());
                        } else if (v.getVitalName().toLowerCase().contains("oodglucos")) {
                            value.setText(v.getValue() + " " + v.getUnit());
                        }
                    }
                }

        }
    }
}
02-10 09:06:39.430 1600-1600/? E/BoostFramework: Exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])' on a null object reference
02-10 09:06:39.476 16831-17154/? E/AndroidCll-SettingsSync: Could not get or parse settings
02-10 09:06:39.547 16831-17062/? E/Appboy v2.5.0 .bo.app.cj: Received server error from request: invalid_api_key
02-10 09:06:39.547 16831-17062/? E/Appboy v2.5.0 .bo.app.ci: Error occurred while executing Braze request: invalid_api_key
02-10 09:06:39.603 16831-17154/? E/AndroidCll-SettingsSync: Could not get or parse settings
02-10 09:06:39.759 1600-1600/? E/BoostFramework: Exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])' on a null object reference
02-10 09:06:41.294 16594-16594/sa.digitrends.rahah.doctor E/AndroidRuntime: FATAL EXCEPTION: main
    Process: sa.digitrends.rahah.doctor, PID: 16594
    java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
        at sa.digitrends.doctor.adapter.AdapterVitalPatient$ViewHolder.updateRecords(AdapterVitalPatient.java:125)
        at sa.digitrends.doctor.adapter.AdapterVitalPatient$ViewHolder$1.onResponse(AdapterVitalPatient.java:106)
        at sa.app.base.retrofit.client.NetworkClient$1.onResponse(NetworkClient.java:60)
        at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
        at android.os.Handler.handleCallback(Handler.java:754)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:163)
        at android.app.ActivityThread.main(ActivityThread.java:6238)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:933)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
02-10 09:06:41.761 16831-16831/? E/Referral: (LauncherApplication.java:890) restarted

3 个答案:

答案 0 :(得分:0)

您可以从onBindView中删除下面的代码段,并将其添加到用户执行相关操作时需要触发的另一种方法中

if (mList.get(position).getSummary() != null) {
        holder.updateRecords(mList.get(position).getSummary());
    } else {
        try {
            holder.callApi(p.getEmail(), position);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

然后您可以在notifydatasetchanged内获得成功响应后执行public void onResponse(boolean result, String completeResponse)

答案 1 :(得分:0)

似乎您有服务器错误

Appboy v2.5.0 .bo.app.cj:收到来自请求的服务器错误:invalid_api_key 02-10 09:06:39.547 16831-17062 /? E / Appboy v2.5.0 .bo.app.ci:执行Braze请求时发生错误:invalid_api_key 02-10 09:06:39.603 16831-17154

答案 2 :(得分:0)

错误是由于NullPointerException

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference

更新如下的updateRecords方法

public void updateRecords(@Nullable ArrayList<Vital> details) {
   mProgressBar.setVisibility(View.GONE);
   if(details == null) {
      return;  
   }
   . . .
   . . .
   . . .
}

通常可以进行进一步的改进。

  • 避免直接从Fragments或具有视图的任何类进行API调用
  • 在后台线程中解析响应。当响应很大时,下面的代码可能会长时间阻塞主线程。
InjectUtils.getGsonObj().fromJson(completeResponse, token)