2016-07-28 53 views
5

我試圖從從Realm數據庫填充的RecyclerView刪除項目運作,我得到了以下錯誤:的Android - 境界 - 對象中刪除 - 對象不再有效對

java.lang.IllegalStateException: Illegal State: 
Object is no longer valid to operate on. Was it deleted by another thread? 

假設 我想我試圖訪問時,它已被刪除,但我不明白在哪裏。

上下文: 我顯示的城市列表和longClicking項目顯示一個對話框,要求確認刪除。

該項目在數據庫中被刪除,因爲當我重新啓動應用程序時,它不再存在。

境界到ArrayList的

public static ArrayList<City> getStoredCities(){ 
     RealmQuery<City> query = getRealmInstance().where(City.class); 
     final RealmResults<City>results = 
       realm.where(City.class) 
         .findAllSorted("timestamp", Sort.DESCENDING); 

     results.size(); 

     ArrayList<City> cityArrayList = new ArrayList<>(); 

     for(int i = 0; i< results.size(); i++){ 
      cityArrayList.add(results.get(i)); 
     } 

     return cityArrayList; 
    } 

對話框代碼

builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { 
    @Override 
    public void onClick(DialogInterface dialogInterface, int i) { 
     RealmHelper.removeCity(cityArrayList.get(position)); 
     cityArrayList.remove(position); 
     mRecyclerView.removeViewAt(position); 
     mCityListAdapter.notifyItemRemoved(position); 
     mCityListAdapter.notifyItemRangeChanged(position, cityArrayList.size()); 
     mCityListAdapter.notifyDataSetChanged(); 
    } 
}); 

境界方法刪除的項目

public static void removeCity(City city){ 
     RealmResults<City> result = realm.where(City.class).equalTo("cityName", city.getCityName()).findAll(); 
     realm.beginTransaction(); 
     result.deleteAllFromRealm(); 
     realm.commitTransaction(); 
} 

日誌

07-28 11:02:08.461 9461-9461/com.ilepez.weatherapp E/AndroidRuntime: FATAL EXCEPTION: main 
Process: com.ilepez.weatherapp, PID: 9461 
java.lang.IllegalStateException: Illegal State: 
Object is no longer valid to operate on. Was it deleted by another thread? 
at io.realm.internal.UncheckedRow.nativeGetString(Native Method) 
at io.realm.internal.UncheckedRow.getString(UncheckedRow.java:153) 
at io.realm.CityRealmProxy.realmGet$cityName(CityRealmProxy.java:75) 
at com.ilepez.weatherapp.data.model.City.getCityName(City.java:41) 
at com.ilepez.weatherapp.adapter.CityListAdapter.onBindViewHolder(CityListAdapter.java:56) 
at com.ilepez.weatherapp.adapter.CityListAdapter.onBindViewHolder(CityListAdapter.java:20) 
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5768) 
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5801) 
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5037) 
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4913) 
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2029) 
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1414) 
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377) 
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:588) 
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3260) 
at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2788) 
at android.view.View.measure(View.java:20151) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6328) 
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 
at android.support.design.widget.NavigationView.onMeasure(NavigationView.java:218) 
at android.view.View.measure(View.java:20151) 
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1108) 
at android.view.View.measure(View.java:20151) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6328) 
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135) 
at android.view.View.measure(View.java:20151) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6328) 
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464) 
at android.widget.LinearLayout.measureVertical(LinearLayout.java:747) 
at android.widget.LinearLayout.onMeasure(LinearLayout.java:629) 
at android.view.View.measure(View.java:20151) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6328) 
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 
at android.view.View.measure(View.java:20151) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6328) 
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464) 
at android.widget.LinearLayout.measureVertical(LinearLayout.java:747) 
at android.widget.LinearLayout.onMeasure(LinearLayout.java:629) 
at android.view.View.measure(View.java:20151) 
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6328) 
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) 
at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:3158) 
at android.view.View.measure(View.java:20151) 
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2594) 
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1549) 
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1841) 
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1437) 
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7403) 
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920) 
at android.view.Choreographer.doCallbacks(Choreographer.java:695) 
at android.view.Choreographer.doFrame(Choreographer.java:631) 
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906) 
at android.os.Handler.handleCall 

適配器代碼

public class CityListAdapter extends RecyclerView.Adapter<CityListAdapter.CityListViewholder>{ 

public interface OnItemClickListener{ 
    void onItemClick(int position); 
} 

public interface OnItemLongClickListener{ 
    void onItemLongClick(int position); 
} 

private static final String LOG_TAG = CityListAdapter.class.getSimpleName(); 

private ArrayList<City> cityArrayList = new ArrayList<>(); 
private Context mContext; 
private OnItemClickListener onItemClickListener; 
private OnItemLongClickListener onItemLongClickListener; 

public CityListAdapter(Context context, ArrayList<City> cityArrayList, OnItemClickListener onItemClickListener, OnItemLongClickListener onItemLongClickListener) { 
    this.cityArrayList = cityArrayList; 
    this.mContext = context; 
    this.onItemClickListener = onItemClickListener; 
    this.onItemLongClickListener = onItemLongClickListener; 
} 

@Override 
public CityListViewholder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.city_item_navigation_viewholder, null); 
    CityListViewholder cityListViewholder = new CityListViewholder(view, parent.getContext()); 
    return cityListViewholder; 
} 

@Override 
public void onBindViewHolder(CityListViewholder holder, int position) { 
    holder.cityName.setText(cityArrayList.get(position).getCityName()); 
    holder.bindClick(position, onItemClickListener); 
    holder.bindLongClick(position, onItemLongClickListener); 
} 

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


public class CityListViewholder extends RecyclerView.ViewHolder{ 

    TextView cityName; 
    ImageView cityIcon; 

    public CityListViewholder(View itemView, Context context) { 
     super(itemView); 
     cityName = (TextView)itemView.findViewById(R.id.city_name); 
     cityIcon = (ImageView)itemView.findViewById(R.id.city_icon); 
    } 

    public void bindClick(final int position, final OnItemClickListener onItemClickListener){ 
     itemView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       onItemClickListener.onItemClick(position); 
      } 
     }); 
    } 

    public void bindLongClick(final int position, final OnItemLongClickListener onItemLongClickListener) { 
     itemView.setOnLongClickListener(new View.OnLongClickListener() { 
      @Override 
      public boolean onLongClick(View view) { 
       onItemLongClickListener.onItemLongClick(position); 
       return true; 
      } 
     }); 
    } 
} 
} 
+0

這個錯誤在哪裏拋出?在適配器中?它是普通的RecyclerView還是RealmRecyclerView? –

+0

它指向一個Realm文件:CityRealmProxy,這使得應用程序崩潰@SuppressWarnings(「cast」) public String realmGet $ cityName(){ proxyState.getRealm $ realm()。checkIfValid(); return(java.lang.String)proxyState.getRow $ realm()。getString(columnInfo.cityNameIndex); } – Isabelle

+0

logcat中的某處它應該告訴你自己的代碼是哪一行觸發了這個錯誤。您可以在這裏複製 –

回答

4

好了,所以你調用adapter.notifyDataSetChanged(),因此任何其他notify___方法是不必要的(數據集變化禁用動畫反正。)

在這種情況下,最簡單(也是最有效)的做法是直接使用RealmResults而不是將每個元素檢索到ArrayList,然後以完全相同的方式使用該元素。

因此,它應該是這樣的

public static RealmResults<City> getStoredCities(){ 
     RealmQuery<City> query = getRealmInstance().where(City.class); 
     return realm.where(City.class) 
         .findAllSorted("timestamp", Sort.DESCENDING); 
} 

而且

public static void removeCity(City city){ 
     final String cityName = city.getCityName(); 
     realm.executeTransaction(new Realm.Transaction() { 
      @Override 
      public void execute(Realm realm) { 
       RealmResults<City> result = realm.where(City.class).equalTo("cityName", cityName).findAll(); 
       result.deleteAllFromRealm(); 
      } 
     }); 
} 

而且

builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { 
    @Override 
    public void onClick(DialogInterface dialogInterface, int i) { 
     RealmHelper.removeCity(getItem(position)); 
    } 
}); 

而且

// dependency: compile 'io.realm:android-adapters:1.3.0' // <-- for Realm 3.x+, use 2.0.0 
public class CityListAdapter extends RealmRecyclerViewAdapter<City, CityListViewHolder> { 

    OnItemClickListener onItemClickListener; 
    OnItemLongClickListener onItemLongClickListener; 

    public CityListAdapter(@NonNull Context context, 
          @Nullable OrderedRealmCollection<City> data, 
          OnItemClickListener onItemClickListener, 
          OnItemLongClickListener onItemLongClickListener) { 
     super(context, data, true); 
     this.onItemClickListener = onItemClickListener; 
     this.onItemLongClickListener = onItemLongClickListener; 
    } 


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

    @Override 
    public void onBindViewHolder(CityListViewholder holder, int position) { 
     holder.cityName.setText(getItem(position).getCityName()); 
     holder.bindClick(position, onItemClickListener); 
     holder.bindLongClick(position, onItemLongClickListener); 
    } 

    public static class CityListViewholder extends RecyclerView.ViewHolder { 
     TextView cityName; 
     ImageView cityIcon; 

     public CityListViewholder(View itemView, 
            Context context) { 
      super(itemView); 
      cityName = (TextView)itemView.findViewById(R.id.city_name); 
      cityIcon = (ImageView)itemView.findViewById(R.id.city_icon); 
     } 

     public void bindClick(final int position, final OnItemClickListener onItemClickListener){ 
      itemView.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        onItemClickListener.onItemClick(position); 
       } 
      }); 
     } 

     public void bindLongClick(final int position, final OnItemLongClickListener onItemLongClickListener) { 
      itemView.setOnLongClickListener(new View.OnLongClickListener() { 
       @Override 
       public boolean onLongClick(View view) { 
        onItemLongClickListener.onItemLongClick(position); 
        return true; 
       } 
      }); 
     } 
    } 
} 

只要結果改變,使用RealmRecyclerViewAdapter將會撥打notifyDataSetChanged()

+0

我目前正在實施:) - 在remove方法中,getdata()似乎不被識別出來'RealmHelper.removeCity(getData()。get(position) );' – Isabelle

+0

'getItem(position)'也適用,如果我知道的話,儘管'getData()'對我有用 – EpicPandaForce

+0

雖然你可能是指你的對話框構建器代碼。這必須是'results.get(position)',但我不確定你在哪裏使用代碼。 – EpicPandaForce