2016-11-14 3 views
0

Я хочу показать результат запроса царства в моем просмотре recycler, используя фильтр. Так я реализовал этот код:Доступ к Realm из неправильной ошибки потока в 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 он выходит из строя, и, с помощью отладчика, я см. это сообщение об ошибке:

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

Проблема заключается в том, что вы запрашиваете аэропортов на потоке пользовательского интерфейса, а затем пытается получить доступ к этим же объектам в другом потоке. Это запрещено.

Метод performFiltering работает на рабочем потоке. Когда он вызывает getFilteredResults, он пытается получить доступ к объекту (item.getName()) объекта Realm, который был запрошен в другом потоке (UI). Как говорится в ошибке, объекты Realm могут быть доступны только в потоке, который они были созданы.

Если вы хотите иметь доступ к объектам, запрошенным в другом потоке, вы можете получить их глубокую копию, чтобы они были отделены от Realm. В вашем примере, после запроса в аэропортах, вы можете использовать метод copyFromRealm(), чтобы получить список регулярных объектов Аэропорта и использовать его оттуда.

+0

спасибо, теперь он работает – nani

+0

@nani Вы можете рассказать мне, какие изменения вы внесли в свой код. Я получаю ту же проблему и не могу найти никакого решения. –

Смежные вопросы