【问题标题】:notifyDataSetChanged() not working with custom Adapter ViewnotifyDataSetChanged() 不适用于自定义适配器视图
【发布时间】:2017-02-07 10:53:54
【问题描述】:

我已经看到这个问题回答了几次,但是没有一个修复对我有用,所以我正在伸出援手。

我已经构建了一个具有 Diolor 可滑动卡片库 (here) 的应用程序,现在我正在尝试实现课程卡片过滤器。

基本上,当用户单击课程过滤器时,我们希望更改馈送到适配器的数据。

目前我正在尝试更新数据并在适配器上调用 notifyDataSetChanged(),期望卡片刷新以显示新数据集,但我发现它根本没有刷新。

对此的任何帮助将不胜感激。

以下所有代码均来自我的 Main Activity。

我声明了我将在活动顶部提供给适配器的数据集:

ArrayList<CourseCardModel> courseCardModelList;

然后在我的 onCreate() 方法中,我实例化适配器,将其附加到视图,然后调用 generateCourseCards() 方法,该方法使用从 firebase 数据库中提取的对象填充 courseCardModelList

// Set up and assign card adapter
    ca = new CustomCardAdapter(CardsActivity.this,     android.R.layout.simple_list_item_1, generateCourseCards());
    flingContainer.init(CardsActivity.this, ca);

generateCourseCards() 方法

private ArrayList<CourseCardModel> generateCourseCards() {

    Toast.makeText(getApplicationContext(), "Retrieving Courses", Toast.LENGTH_LONG).show();

    courseCardModelList = new ArrayList<CourseCardModel>();

    dbref =  FirebaseDatabase.getInstance().getReference().child("courses");



    // Retrieve the course data from Firebase db and cast as Course object
    dbref.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {
            Log.e("Count " ,"" + snapshot.getChildrenCount());
            for (DataSnapshot postSnapshot: snapshot.getChildren()) {

                c = postSnapshot.getValue(Course.class);

                System.out.println(c.getCourseName());

                CourseCardModel model = new CourseCardModel();
                 model.setCourse(c);

                courseCardModelList.add(model);

            }

            Collections.shuffle(courseCardModelList);
            ca.notifyDataSetChanged();


        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e("The read failed: ", databaseError.getMessage());
        }

    });

    return courseCardModelList;

}

尝试更新数据集(暂时简单洗牌)并刷新卡片

// Shuffle the collection and refresh the cards
            Collections.shuffle(courseCardModelList);
            ca.notifyDataSetChanged();

编辑:添加适配器代码

public class CustomCardAdapter extends ArrayAdapter {

private TextView courseName, uniName, entryStandards, courseDuration, studyMode, qualification,
        studentSatisfaction, gradProspects, t1, t2, t3, t4, t5, t6;

ArrayList<CourseCardModel> items;



View v;


LayoutInflater vi;

public CustomCardAdapter(Activity context, int resource, ArrayList<CourseCardModel> courses) {
    super(context, resource, courses);

    vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}


@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    v = convertView;
    if (v == null) {

        v = vi.inflate(R.layout.course_card_inner_template, parent , false);
    }

    CourseCardModel c = (CourseCardModel) getItem(position);

    if (c != null) {

        courseName = (TextView) v.findViewById(R.id.courseCardCourseName);
        uniName = (TextView) v.findViewById(R.id.courseCardUniName);
        entryStandards = (TextView) v.findViewById(R.id.courseCardEntryStandards);
        courseDuration = (TextView) v.findViewById(R.id.courseCardCourseDuration);
        studyMode = (TextView) v.findViewById(R.id.courseCardStudyMode);
        qualification = (TextView) v.findViewById(R.id.courseCardQualification);
        studentSatisfaction = (TextView) v.findViewById(R.id.courseCardStudentSatisfaction);
        gradProspects = (TextView) v.findViewById(R.id.courseCardGraduateProspects);


        t1 = (TextView) v.findViewById(R.id.cardTV1);
        t2 = (TextView) v.findViewById(R.id.cardTV2);
        t3 = (TextView) v.findViewById(R.id.cardTV3);
        t4 = (TextView) v.findViewById(R.id.cardTV4);
        t5 = (TextView) v.findViewById(R.id.cardTV5);
        t6 = (TextView) v.findViewById(R.id.cardTV6);

        v.setBackgroundResource(R.drawable.newcard);

        courseName.setText(c.getCourse().getCourseName());
        uniName.setText(c.getCourse().getUniversity());
        entryStandards.setText(c.getCourse().getEntryStandards());
        courseDuration.setText(c.getCourse().getCourseDuration());
        studyMode.setText(c.getCourse().getStudyMode());
        qualification.setText(c.getCourse().getQualification());
        studentSatisfaction.setText(c.getCourse().getStudentSatisfaction().toString() + " / 5");
        gradProspects.setText(c.getCourse().getGradProspects() + " / 100");



    }

    if(position ==0)
    {
        //float alpha = (float) 0.8;
        //v.setAlpha(alpha);
        courseName.setVisibility(View.VISIBLE);
    }

    else if (position == 1){

        // Prepare the View for the animation
        v.setVisibility(View.VISIBLE);

        float alpha = (float) 0.8;
        float alpha2 = (float) 0.3;
        courseName.setAlpha(alpha2);
        uniName.setAlpha(alpha2);
        entryStandards.setAlpha(alpha2);
        courseDuration.setAlpha(alpha2);
        studyMode.setAlpha(alpha2);
        qualification.setAlpha(alpha2);
        studentSatisfaction.setAlpha(alpha2);
        gradProspects.setAlpha(alpha2);
        t1.setAlpha(alpha2);
        t2.setAlpha(alpha2);
        t3.setAlpha(alpha2);
        t4.setAlpha(alpha2);
        t5.setAlpha(alpha2);
        t6.setAlpha(alpha2);
        v.setAlpha(alpha);


    }
    else {
        v.setVisibility(View.INVISIBLE);
    }

    return v ;
}


public void updateData(ArrayList<CourseCardModel> courseCardModels) {

    this.items = courseCardModels;
    notifyDataSetChanged();

}

}

【问题讨论】:

  • 用你的适配器类更新你的问题。
  • 如果您在 CustomAdapter 中使用 BaseAdapter,那么您将使用 notifyDataSetInvalidated();方法

标签: java android android-arrayadapter notifydatasetchanged


【解决方案1】:

这个方法有问题。

public void updateData(ArrayList<CourseCardModel> courseCardModels) {
    this.items = courseCardModels;
    notifyDataSetChanged();
}

在这里,您正在为您的适配器提供另一个数组引用。

改写如下。

public void updateData(ArrayList<CourseCardModel> courseCardModels) {
    this.items.clear();
    this.items.addAll(courseCardModels);
    notifyDataSetChanged();
}

【讨论】:

  • 您好,Pratik,感谢您的回复。我从未真正调用过该方法,但现在我已将代码更改为您的建议,并在我的主活动中调用 - 将它传递给已洗牌的 courseCardModelList,现在卡片从活动中消失,但不再出现。有什么想法吗?
  • 我已经添加了主要活动的完整代码。要查看的主要部分是附加到 openFilterDialog 方法中的按钮的 onClickListeners。我无法弄清楚如何从本质上“刷新”卡片。因此,在dialogRandomButton onClickListener 中,我想要做的就是“洗牌”并让它们再次出现。
【解决方案2】:

如果没有提供适配器类,我的第一个猜测是你把引用搞砸了。也许您正在改组适配器未引用的数据。一旦你分享了你的适配器的代码,我会更新我的答案。

== 编辑 ==

避免从适配器引用某些外部数据集合,并更新引用的数据。更新适配器/列表数据应使用适配器的接口和方法完成,例如 add()addAll()remove() (父)适配器可能会克隆/复制您的数据,在这种情况下更新外部/引用的集合没有任何好处。

【讨论】:

  • @freshwaterjoe 您实现此代码的方式 Collections.shuffle(courseCardModelList); ca.notifyDataSetChanged();无法到达。您改组并通知了两者都不用于更新代码的适配器。在您实际初始化适配器的相同方法上通知 dataSetChanged。
  • 我已将代码修改为使用ca.clear(),后跟ca.addAll(courseCardModelList)ca.notifyDataSetChange。当我对此进行测试时,它只会使卡片消失。有什么想法吗?
【解决方案3】:

您正在扩展一个 ArrayAdapter,其中包含他自己的模型数组(传递给构造函数的数组)。如果您想更新项目,请执行以下操作:

ca.clear(); 
for (CourseCardModel object : courseCardModelList) {
   ca.insert(object, ca.getCount());
}

ca.notifyDataSetChanged();

或者您可以覆盖 getItem 方法并从您的 items 数组中返回一个项目。

另一种选择是扩展 BaseAdapter 而不是 ArrayAdapter。

【讨论】:

  • 您好,感谢您的回复。我刚刚尝试过,但发现它仍然无法正常工作。当我运行该代码时,卡片视图只是冻结了一段时间然后消失了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多