onBindViewHolder(VH,position)在使用notifyItemChanged()

时间:2016-04-17 03:11:48

标签: android android-layout android-recyclerview android-viewholder

EDIT2 :我在holder.showTaskRecyclerViewfalse隐藏视图的情况下明确说明,以便明确涵盖true和{{ 1}} false中的案例。我仍然有同样的问题。

EDIT1:我应该补充一点,如果我使用onBindViewHolder代替tasksRecyclerViewnotifyDataSetChanged()的显示和隐藏效果会很好,但这会禁用动画而且成本更高。

我的ViewHolder中有一个名为notifyItemChanged()的RecyclerView,只要单击该视图,就会显示和隐藏它。 (这是主要的RecyclerView里面的RecyclerView,所以说。):

tasksRecyclerView

目前,代码中的onClick设置为切换ViewHolder中定义的变量( public class ViewHolder extends RecyclerView.ViewHolder { public ImageView routineStateImgView; public TextView alarmTextView; public TextView routineNameTextView; public RecyclerView tasksRecyclerView; public boolean showTaskRecyclerView = false; public ViewHolder(View routineItemView){ super(routineItemView); routineItemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //toggle showing TaskRecyclerView showTaskRecyclerView = !showTaskRecyclerView; notifyItemChanged(getAdapterPosition()); } }); routineStateImgView = (ImageView) routineItemView.findViewById(R.id.routineStateImgView); alarmTextView = (TextView) routineItemView.findViewById(R.id.alarmTextView); routineNameTextView = (TextView) routineItemView.findViewById(R.id.routineNameTextView); tasksRecyclerView = (RecyclerView) routineItemView.findViewById(R.id.tasksRecyclerView); } public ImageView getRoutineStateImgView() { return routineStateImgView; } public TextView getAlarmTextView(){ return alarmTextView; } public TextView getRoutineNameTextView(){ return routineNameTextView; } public RecyclerView getTasksRecyclerView(){ return tasksRecyclerView; } } ),然后调用showTaskRecyclerView以动画更新项目更改。

当调用OnBindViewHolder时,它会再次检查切换变量(notifyItemChanged(getAdapterPosition()))的状态,并根据变量隐藏或取消隐藏RecyclerView。您可以在此代码段中的Log.d方法行之后的代码中看到此逻辑:

showTaskRecyclerView

我希望每次点击都会看到RecyclerView隐藏或取消隐藏。但是,我每2次点击后才会看到隐藏/取消隐藏行为。

hide-unhide-with-2-clicks

点击5次后,这是Log.d的输出:

public void onBindViewHolder(RoutinesRecyclerViewAdapter.ViewHolder holder, int position) {
    //Replace contents of view with data from item in adapterRoutinesList at position.
    Routine routine = adapterRoutinesList.get(position);
    TasksRecyclerViewAdapter mTasksRecyclerViewAdapter = null;

    if(routine == null){
        holder.getRoutineStateImgView().setImageResource(android.R.color.transparent);
        holder.getAlarmTextView().setText("");
        holder.getRoutineNameTextView().setText("");
        holder.getTasksRecyclerView().setVisibility(View.GONE);
    }else{
        DateFormat dayTimeFormat = new SimpleDateFormat("HH:mm", Locale.US);
        String dayTimeString = dayTimeFormat.format(routine.getWakeupTime().getTime());
        holder.getAlarmTextView().setText(dayTimeString);
        holder.getRoutineNameTextView().setText(routine.getName());
        if(routine.getEnableRoutine()) {
            holder.getRoutineStateImgView().setImageResource(R.drawable.check_mark);
        }
        else{
            holder.getRoutineStateImgView().setImageResource(R.drawable.x_mark);
        }

        Log.d(TAG, "position: " + position + " holder: " + holder + " show?: " + holder.showTaskRecyclerView);
        if(holder.showTaskRecyclerView) {
            TasksManager mTasksManager = adapterTasksListCache.get(routine.getId());
            if (mTasksManager == null) {
                mTasksManager = new TasksManager(routine.getId());
                mTasksManager.readTasksFromDisk(mContext);
                adapterTasksListCache.put(routine.getId(), mTasksManager);
            }

            mTasksRecyclerViewAdapter = adapterTasksViewCache.get(routine.getId());
            if (mTasksRecyclerViewAdapter == null) {
                mTasksRecyclerViewAdapter = new TasksRecyclerViewAdapter(
                        mContext,
                        position,
                        mTasksManager.getTasksListFromCache(),
                        mRequestImageCaptureCallBack,
                        mTaskEditTextListener);
                adapterTasksViewCache.put(routine.getId(), mTasksRecyclerViewAdapter);
            }
            RecyclerView.LayoutManager mTaskLayoutManager = new LinearLayoutManager(mContext);
            holder.getTasksRecyclerView().setLayoutManager(mTaskLayoutManager);
            holder.getTasksRecyclerView().setAdapter(mTasksRecyclerViewAdapter);
            holder.getTasksRecyclerView().setHasFixedSize(true);
            holder.getTasksRecyclerView().setVisibility(View.VISIBLE);
        }
        else{
            holder.getTasksRecyclerView().setVisibility(View.GONE);
        }
    }
}

我的解释是使用notifyItemChanged提示使用相同ViewHolder的2个副本用于过渡动画目的(一个具有旧视图状态,一个具有新状态)。但是,旧副本中的变量副本错误地更改。我假设我对notifyItemChanged如何工作有错误的理解,所以我来这里寻求帮助:/

此外,当我点击非常快时,我不知道是什么原因引起了这个问题:如果我点击得足够快(大约快到不到半秒),我看不出任何变化。

logcat显示以下内容:

04-16 21:33:37.026 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: false
04-16 21:33:42.626 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: false
04-16 21:33:44.511 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: true
04-16 21:33:46.274 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: true
04-16 21:33:47.938 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{263b1503 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: false
04-16 21:41:52.756 13522-13522/co.edu.javeriana.faros D/RoutinesViewAdapter: position: 0 holder: ViewHolder{883eb98 position=0 id=-1, oldPos=-1, pLpos:-1 no parent} show?: false

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

holder.showTaskRecyclerViewfalse时,您需要实现条件的逻辑。

View维持其状态,因此您必须明确修改它们。放置一些逻辑来隐藏它并检查它是否有效。

答案 1 :(得分:0)

我通过在ListArray之外为ViewHolder定义showTaskRecyclerView并为适配器中的每个项目ViewHolder来解决此问题。

通过这种方式,新旧showTaskRecyclerView每个项目都会看到相同的单showTaskRecyclerView,而ViewHolder中每个项目的new_dict = {datetime.strptime(key, "%Y-%m-%d %H:%M:%S"): val for key, val in alerts['alert_date'].items()} 不会同步datetime.strptime