在更新数据集之前绘制RecyclerView

时间:2015-06-03 19:24:06

标签: java android android-recyclerview onactivityresult android-viewholder

我有一个片段,我有一个RecyclerView:

public class AlarmListFragment extends Fragment{

    public AlarmListAdapter alarmListAdapter;
    RecyclerView recyclerViewAlarms;

    public AlarmListFragment() { }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_alarm_list, container, false);

        recyclerViewAlarms = (RecyclerView) rootView.findViewById(R.id.fragment_alarm_list_card_list);
        recyclerViewAlarms.setHasFixedSize(true); // performance!
        LinearLayoutManager llm = new LinearLayoutManager(getActivity());
        recyclerViewAlarms.setLayoutManager(llm);
        alarmListAdapter = new AlarmListAdapter(getActivity());
        recyclerViewAlarms.setAdapter(alarmListAdapter);

        return rootView;
    }

它使用以下适配器:

public class AlarmListAdapter extends RecyclerView.Adapter<AlarmListViewHolder> {

private List<AlarmModel> alarmModelDataSet;
private Context context;

public AlarmListAdapter(Context context) {
    this.alarmModelDataSet = AlarmModel.listAll(AlarmModel.class);
    this.context = context;
}

@Override
public AlarmListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View view = inflater.inflate(R.layout.alarm_list_card, parent, false);
    return new AlarmListViewHolder(view);
}

@Override
public int getItemCount() {
    return (int) AlarmModel.count(AlarmModel.class, null, null);
}

@Override
public void onBindViewHolder(AlarmListViewHolder holder, int position) {
    // todo wait here until alarmModel is added to DataSet
    AlarmModel alarmModel = alarmModelDataSet.get(position);
    *** update GUI stuff ***
    if (alarmModel.isEnabled()) {
        *** update GUI stuff ***
    }
    if (alarmModel.isRepeatWeekly()) {
        *** update GUI stuff ***
    } else {
        *** update GUI stuff ***
    }
    if (!alarmModel.isEnabled()){
        *** update GUI stuff ***
    }
}

public List<AlarmModel> getDataSet(){
    return alarmModelDataSet;
}

public int getIndex(AlarmModel alarmModel){
    for (AlarmModel _item : alarmModelDataSet){
        if (_item.getId().equals(alarmModel.getId())){
            return alarmModelDataSet.indexOf(_item);
        }
    }
    return -1;
}

public void addOrUpdateAlarm(AlarmModel alarmModel){
    int position = getIndex(alarmModel);
    if (position >= 0) {
        updateAlarm(alarmModel, position);
    } else {
        addAlarm(alarmModel);
    }
}

private void addAlarm(AlarmModel alarmModel){
    alarmModelDataSet.add(alarmModel);
    notifyItemInserted(alarmModelDataSet.size() - 1);
}

private void updateAlarm(AlarmModel alarmModel, int position){
    alarmModelDataSet.set(getIndex(alarmModel), alarmModel);
    notifyItemChanged(position);
}

public void deleteAlarm(AlarmModel alarmModel) {
    alarmModel.setIsEnabled(false);
    AlarmManagerBroadcastReceiver.setAlarms(context);
    int position = getIndex(alarmModel);
    alarmModelDataSet.remove(position); // deletes out of class internal List
    notifyItemRemoved(position); // notifies list fragment of deletion
}

public void enableOrDisableAlarm(int position){
    AlarmModel alarmModel = alarmModelDataSet.get(position);
    alarmModel.setIsEnabled(!alarmModel.isEnabled());
    notifyItemChanged(position);
}

每个alarmModel都保存在一个工作正常的数据库中,因此我删除了有关数据库的代码。 第一个代码段中的片段使用startActivityForResult打开一个活动,该活动允许创建存储在另一个alarmModel中的新警报。这个新的alarmModel保存到数据库中,其ID通过此代码返回到我的片段

Intent intent = new Intent();
intent.putExtra("id", alarmDetails.getId());
intent.putExtra("delete", false);
setResult(RESULT_OK, intent);
supportFinishAfterTransition();

该结果由片段的onActivityResult方法接收:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_ADD_ALARM_ID) {
        long id = data.getLongExtra("id", -7777);

        if (data.getBooleanExtra("delete", false)) { // delete
            alarmListAdapter.deleteAlarm(AlarmModel.findById(AlarmModel.class, id));
        } else { // add or update
            alarmListAdapter.addOrUpdateAlarm(AlarmModel.findById(AlarmModel.class, id));
        }
    }
}

在完成所有这些代码后,我终于能够描述我的问题了:

在代码甚至达到addOrUpdate方法之前,调用适配器的onBindViewHolder方法并生成IndexOutOfBoundsException,因为AlarmModel alarmModel = alarmModelDataSet.get(position);刚刚添加的alarmModel想要绘制但是尚未添加到DataSet。

一切正常(虽然应用程序变得很慢)当RecyclerView有~10 +个项目,因为onBindViewHolder首先为每个其他项目调用,并且在计算了9个其他项目之后addOrUpdate方法已经完成

我犯了致命的错误或者我还没找到的方法,这对我有帮助吗?我想过使用两个线程让一个人等到另一个线程完成但不确定怎么做,因为我已经知道你应该永远不会阻止Ui-Thread。

编辑1

为了尝试在适配器静态中创建add,update和delete方法,我完全删除了List alarmModelDataSet并且每次都查询数据库。虽然我最初的计划没有成功,但我注意到它通过使方法变得如此缓慢以至于一切正常工作来解决我的问题。但是,由于这不是一个真正的解决方案,只是简单的编码工作得很慢,我对此并不满意......

感谢所有人阅读这个长期的问题/问题

Tafelbomber

0 个答案:

没有答案