簡體   English   中英

notifyDataSetChanged()在自定義RecyclerView適配器上不起作用

[英]notifyDataSetChanged() not working on custom RecyclerView adapter

我試圖創建一個recyclerView來顯示當前狀態欄通知的列表。 我創建了一個自定義適配器( NotiRecyclerAdapter ),該適配器采用NotificationItemInformationList

public class NotificationItemInformation
{
  int iconId,noitId;
  String packageName;
  Drawable notiIcon;
}

我正在使用SQLite數據庫存儲所有通知。 每當發布或刪除通知時, NotificationListenerService都會從數據庫中寫入和刪除。

我使用一種稱為

public List<NotificationItemInformation> ReadNotilist (Context context);

(位於myDBHelper內部)將DB的內容讀取到NotificationItemInformation List ,該List稱為data (在我的Main Activity中是global,public和static)。 然后我使用adapter (在Main Activity中也是global,public和static)來獲取data並將其設置到MainActivityonCreate方法內的RecyclerView

到目前為止,一切工作正常。 我可以看到RecyclerView填充了當前的StatusBar通知。

問題是,直到我重新啟動活動,列表才會更新(如果有新的通知到來)。 我嘗試打電話給...

MainActivity.data.clear();
MainActivity.data = dbh.ReadNotilist(this); // dbh is DBhelper object
MainActivity.adapter.notifyDataSetChanged();

...在我的NotificationListenerService onNotificationPosted (添加到數據庫中之后)。 但是,直到我重新啟動活動, RecyclerView仍不會得到更新。

如果您想看一下,這是我的MainActivity

public class MainActivity extends AppCompatActivity
{

    SQLiteDatabase db;
    DBHelper dbh;

    RecyclerView notificationIconRecyclerView;
    public static NotiRecyclerAdapter adapter;
    public static List<NotificationItemInformation> data = Collections.EMPTY_LIST;

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

        dbh = new DBHelper(this);
        db = dbh.getDb();
        notificationIconRecyclerView = (RecyclerView) findViewById(R.id.notificationIconRecyclerView);
        data = dbh.ReadNotilist(this);
        adapter = new NotiRecyclerAdapter(this,data);
        notificationIconRecyclerView.setAdapter(adapter);
        notificationIconRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,true));
    }
}

這是我為RecyclerView定制的適配器

public class NotiRecyclerAdapter extends RecyclerView.Adapter<NotiRecyclerAdapter.MyViewHolder>
{

    private LayoutInflater inflater;
    List<NotificationItemInformation> data = Collections.emptyList();

    NotiRecyclerAdapter(Context context, List<NotificationItemInformation> data)
    {
        inflater = LayoutInflater.from(context);
        this.data = data;
    }


    @Override
    public void registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer)
    {
        super.registerAdapterDataObserver(observer);
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View view = inflater.inflate(R.layout.custom_recyclerview_item,parent,false);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position)
    {
        NotificationItemInformation current = data.get(position);
        holder.recyclerItemIcon.setImageDrawable(current.notiIcon);
    }

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

    public class MyViewHolder extends RecyclerView.ViewHolder
    {
        ImageView recyclerItemIcon;
        public MyViewHolder(View itemView)
        {
            super(itemView);
            recyclerItemIcon = itemView.findViewById(R.id.notiRecyclerItemIcon);
        }
    }

}

不要重置對數據對象的引用。 而是嘗試這樣的事情:

MainActivity.data.clear();
MainActivity.data.addAll(dbh.ReadNotilist(this));
MainActivity.adapter.notifyDataSetChanged();

在適配器的構造函數中,您編寫

this.data = data;

這會將傳遞給構造函數的List<NotificationItemInformation>分配給適配器的data字段。 您的適配器的結構如下:

adapter = new NotiRecyclerAdapter(this,data);

這意味着您的MainActivity.data字段和adapter.data字段都引用同一列表。

稍后您寫:

MainActivity.data.clear();
MainActivity.data = dbh.ReadNotilist(this);
MainActivity.adapter.notifyDataSetChanged();

第一行清除MainActivity.data adapter.data (請記住,由於適配器的構造方式,它們是相同的列表)。 第二行將新列表分配給MainActivity.data ,但不以任何方式影響adapter.data 第三行通知適配器數據集已更改(數據集已更改;數據集已清除),但是適配器不會從dbh.ReadNotilist() “看到”新信息。

AChez9的答案之所以有效,是因為使用addAll()而不是賦值( = )意味着MainActivity.dataadapter.data仍指向同一List ,因此適配器將“查看”新信息。

這就是為什么當您從外部來源接受列表副本時通常正確的做法。 換句話說,您的適配器的構造函數可能想要這樣做:

this.data = new ArrayList<>(data);

這意味着從傳遞給它的列表更改(在本例中為MainActivity.data )中,它是“安全的”。 但這意味着您還需要公開一種活動來正確更新適配器。 我建議這樣的方法:

public void updateData(List< NotificationItemInformation> data) {
    this.data = new ArrayList<>(data);
    notifyDataSetChanged();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM