2017-10-20 75 views
0

我已經創建了一個自定義listadapter其中包含三個組件歌曲標題,歌曲編號和最喜歡的圖標。收藏夾圖標用於標記或取消標記列表中的收藏項目。 請看附件中的視頻,瞭解問題所在。當我滾動我的android應用程序中的自定義列表,然後最喜歡的圖標,這是自定義適配器的一部分自己更改

Video

當我點擊的明星,圖標被選中/未選中,並觸發setOnFavoriteChangeListener事件。如果我檢查isFavorite狀態並相應地更新數據庫。這裏是適配器的全碼:

public class song_index_adapter extends ArrayAdapter<song_index_model>{ //implements View.OnClickListener { 
private ArrayList<song_index_model> dataSet; 
Context mContext; 
private int lastPosition = -1; 

public song_index_adapter(ArrayList<song_index_model> data, Context context) { 
    super(context, R.layout.song_index_row, data); 
    this.dataSet = data; 
    this.mContext=context; 
} 
// View lookup cache 
private static class ViewHolder { 
    TextView txt_sno; 
    TextView txt_title; 
    MaterialFavoriteButton favorite; 
} 
@NonNull 
@Override 
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { 
    // Get the data item for this position 
    final song_index_model dataModel = getItem(position); 

    // Check if an existing view is being reused, otherwise inflate the view 
    final ViewHolder viewHolder; // view lookup cache stored in tag 

    final View result; 

    if (convertView == null) { 
     viewHolder = new ViewHolder(); 
     LayoutInflater inflater = LayoutInflater.from(getContext()); 
     convertView = inflater.inflate(R.layout.song_index_row, parent, false); 

     viewHolder.txt_sno = (TextView) convertView.findViewById(R.id.sno); 
     viewHolder.txt_title = (TextView) convertView.findViewById(R.id.songTitle); 
     viewHolder.favorite = (MaterialFavoriteButton) convertView.findViewById(R.id.indexfav); 

     result=convertView; 

     convertView.setTag(viewHolder); 
    } else { 
     viewHolder = (ViewHolder) convertView.getTag(); 
     result=convertView; 
    } 

    Animation animation = AnimationUtils.loadAnimation(mContext, (position > lastPosition) ? R.anim.up_from_bottom : R.anim.down_from_top); 
    result.startAnimation(animation); 
    lastPosition = position; 

    viewHolder.txt_sno.setText(dataModel.getSno()); 
    viewHolder.txt_title.setText(dataModel.getTitle()); 

    //--- following conditional statements take care to 
    //--- not to show a star with the index letter 
    if(viewHolder.txt_sno.getText().toString().equals("")) 
     viewHolder.favorite.setVisibility(View.GONE); 
    else 
     viewHolder.favorite.setVisibility(View.VISIBLE); 

    viewHolder.favorite.setFavorite(dataModel.getFav()); 

    int fsize = (gvar.fontsize * gvar.fontstep) + gvar.fontmin; 
    viewHolder.txt_title.setTextSize(fsize); 
    viewHolder.txt_sno.setTextSize(fsize); 

    viewHolder.favorite.setOnFavoriteChangeListener(new MaterialFavoriteButton.OnFavoriteChangeListener() { 
     @Override 
     public void onFavoriteChanged(MaterialFavoriteButton buttonView, boolean isfavorite) { 
      DBHelper db = new DBHelper(mContext); 
      SQLiteDatabase sdb = db.getWritableDatabase(); 

      boolean isUpdate = db.updateData(gvar.table,dataModel.getSno(),dataModel.getTitle(),dataModel.getSong(),dataModel.getCategory(),isfavorite); 
      if(!isUpdate) 
       Toast.makeText(mContext, "Song Selection could not be saved", Toast.LENGTH_SHORT).show(); 
      else { 
       Toast.makeText(mContext, "Updated " + dataModel.getSno(), Toast.LENGTH_SHORT).show(); 
       Log.e("UPDATED", dataModel.getSno() + " " + isfavorite); 
      } 
     } 
    }); 
    return convertView; 
} 

}

此事件是其在listview設置adapter文件中,它基本上檢查喜愛的明星的狀態並更新歌曲的狀態在數據庫中。 您可以看到提示關於更新的消息Toast

我的問題是,即使我只是上下滾動而不按星形圖標,那麼setOnFavoriteChangeListener事件也會持續發射。這可以在Toast消息和Log記錄中看到。我附上日誌記錄的快照,供您查看。 Log record

我個人改變了最開始只有歌曲9和42的最喜歡的圖標,最後是35。在兩者之間,我只是不斷滾動,你可以看到UPDATE是如何發生的。

我的目標是標記喜歡的物品列表。

爲什麼setOnFavoriteChangeListener沒有我碰它就會被解僱。

是否有任何其他方法從列表中標記最喜歡的項目並將它們保存在數據庫中。

在此先感謝

+0

你能發佈完整的適配器代碼嗎?這肯定會有所幫助。 –

+0

以下是完整的適配器代碼 – pamo

+0

我沒有看到任何適配器代碼。 –

回答

0

我想我找到了你的問題。它與你回收ListView項目的事實有關。在初始加載過程中,一切正常,並且沒有任何選擇,並且調用dataModel.getFav()返回false,因此當您調用viewHolder.favorite.setFavorite()時,MaterialFavoriteButton不會觸發它的OnFavoriteChangeListener。原因在於,因爲它在內部檢查新的最愛狀態是否與最後一次不同,以防止不必要的工作(I checked the source code)。但是,一旦您做出選擇,您的onFavoriteChanged將被解僱,因爲新狀態不同,然後您將值存儲在數據庫中。當你開始滾動時,你的問題就會出現,因爲你的視圖被回收了,MaterialFavoriteButton最喜歡的狀態將會設置,但是當你調用dataModel.getFav()時,它會返回false並且將MaterialFavoriteButton的最喜歡狀態改回false。從而導致您的MaterialFavoriteButton的舊OnFavoriteChangeListener再次觸發(因此爲什麼該按鈕沒有收藏)。它也在使用它的以前的dataModel更新數據庫(注意:這是一個關閉問題),這就是爲什麼你看到它使用屏幕滾動視圖中的文本。原因是舊的OnFavoriteChangeListener被調用,因爲視圖正在被回收,並且仍然有初始加載期間傳遞給它的實例。因此,一旦所有視圖都被填充以填充整個屏幕,如果您滾動第一個視圖以關閉屏幕,則將傳遞給getView()作爲convertView。您應該將調用viewHolder.favorite.setOnFavoriteChangeListener移動到setFavorite之前( )電話。如果你在代碼中放置一個調試語句,並通過對viewHolder.favorite.setFavorite()的調用,你應該看到我在說什麼。我希望這一切都能讓你有所收穫。如果沒有,評論和我嘗試給你更多的幫助。我推薦的解決方案是暫緩數據庫寫操作,直到按下保存按鈕或Activity/Fragment暫停或停止,並將最喜歡的狀態存儲在使用getView(...)位置參數訪問的ArrayList中。這樣更有效率,因爲無論ListView何時滾動,您都不需要經常訪問數據庫。

相關問題