2016-11-14 5 views
0

フィルタを使用して、リサイクルビューで領域クエリの結果を表示したいとします。 だから私はこのコードを実装しました:recyclerviewの不正なスレッドエラーによる領域アクセス

public class ListAirportFragment extends Fragment 
{ 
Realm realm; 
List<AirportR>airports = new ArrayList<>(); 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) 
{ 
    View rootView = inflater.inflate(R.layout.fragment_list_airport, container, false); 

    RealmConfiguration defaultConfig = new RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build(); 
    realm = Realm.getInstance(defaultConfig); 

    RecyclerView recyclerView = (RecyclerView)rootView.findViewById(R.id.recyclerview); 
    SearchView searchView = (SearchView)rootView.findViewById(R.id.searchview); 

    recyclerView.setHasFixedSize(true); 


    //final RealmResults<AirportR> airps = realm.where(AirportR.class).findAllAsync(); 
    final RealmResults<AirportR> airps = realm.where(AirportR.class).findAll(); 

    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 
    final AirportAdapter adapter = new AirportAdapter(airports,getActivity()); 
    recyclerView.setAdapter(adapter); 


    realm.executeTransaction(new Realm.Transaction() 
    { 
     @Override 
     public void execute(Realm realm) 
     { 
      for (int i = 0; i<airps.size();i++) 
      { 
      airports.add(airps.get(i)); 
      adapter.notifyDataSetChanged(); 
      } 

     } 
    }); 

/*  airps.addChangeListener(new RealmChangeListener<RealmResults<AirportR>>() { 
     @Override 
     public void onChange(RealmResults<AirportR> element) 
     { 
      for (int i = 0; i<element.size();i++) 
      { 
      airports.add(element.get(i)); 
      adapter.notifyDataSetChanged(); 
      } 


     } 
    }); */ 

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() 
    { 
     @Override 
     public boolean onQueryTextSubmit(String query) 
     { 
      return false; 
     } 

     @Override 
     public boolean onQueryTextChange(String newText) 
     { 
      adapter.getFilter().filter(newText); 
      return true; 
     } 
    }); 

    return rootView; 
} 

} 

をし、これが私のアダプタです:

public class AirportAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable 
{ 

private List<AirportR>originalAirports; 
private List <AirportR>listAirports; 
private Context context; 

public AirportAdapter(List<AirportR> airports, Context context) 
{ 
    this.originalAirports = airports; 
    this.listAirports = airports; 
    this.context = context; 
} 

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
{ 
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.airport_show, parent,false); 
    AirportClass holder = new AirportClass(view); 
    return holder; 
} 

@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) 
{ 
    AirportR airportR = originalAirports.get(position); 

String country = airportR.getIsoCountry().toLowerCase()+".png"; 

int imgID = context.getResources().getIdentifier(country , "drawable", context.getPackageName()); 

AirportClass mHolder = (AirportClass)holder; 

mHolder.image.setImageResource(imgID); 
mHolder.country.setText(airportR.getIsoCountry()); 
mHolder.name.setText(airportR.getName()); 

} 

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

@Override 
public Filter getFilter() 
{ 
    return new Filter() 
    { 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) 
     { 
      List<AirportR> filteredResults = null; 
      if (constraint.length() == 0) 
      { 
       filteredResults = originalAirports; 
      } 
      else 
      { 
      filteredResults = getFilteredResults(constraint.toString().toLowerCase()); 
      } 

      Log.d("const",String.valueOf(constraint.length())); 
      FilterResults results = new FilterResults(); 
      results.values = filteredResults; 

      return results; 
     } 


     protected List<AirportR> getFilteredResults(String constraint) 
     { 
      List<AirportR> results = new ArrayList<>(); 

      for (AirportR item : originalAirports) 
      { 
       if (item.getName().toLowerCase().contains(constraint)) 
       { 
        results.add(item); 
       } 
      } 
      return results; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) 
     { 
      listAirports = (List<AirportR>)results.values; 
      AirportAdapter.this.notifyDataSetChanged(); 

     } 
    }; 
} 


private class AirportClass extends RecyclerView.ViewHolder 
{ 
    TextView name, country; 
    ImageView image; 

    public AirportClass(View itemView) 
    { 
     super(itemView); 

     name = (TextView)itemView.findViewById(R.id.name); 
     country = (TextView)itemView.findViewById(R.id.country); 
     image = (ImageView)itemView.findViewById(R.id.imageView); 

    } 
} 
} 

問題がある:私はそれをデバッガで、クラッシュとsearchViewために何かを置くしようとすると、Iこのエラーメッセージを参照してください:

W/Filter: An exception occured during performFiltering()! 
     java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. 

どうしたのですか?私はユーザーfindAllAsync()の結果を取得する前に、私は単純なfindAll()を使用した後、私は同じエラーメッセージを取得...それは同じスレッドではないのですか?または、フィルタに他の問題がありますか?

おかげ

答えて

3

問題は、UIスレッド上の空港を問い合わせることで、後で別のスレッドでこれらの同じオブジェクトにアクセスしようとします。これは許可されていません。

メソッドperformFilteringは、ワーカースレッド上で実行されます。 getFilteredResultsを呼び出すと、別のスレッド(UI)で照会されたレルムオブジェクトのプロパティ(item.getName())にアクセスしようとします。エラーが示すように、Realmオブジェクトは作成されたスレッドでのみアクセスできます。

他のスレッドで照会したオブジェクトにアクセスできるようにするには、そのオブジェクトの詳細コピーを取得して、それらがレルムから切り離されるようにすることができます。あなたの例では、空港を照会した後、方法copyFromRealm()を使用して、通常の空港オブジェクトのリストを取得し、そこから使用することができます。

+0

ありがとうございました。 – nani

+0

@naniあなたのコードでどのような変更を行ったか教えてください。私は同じ問題を抱えており、解決策を見つけることができません。 –

関連する問題