Комната LiveData, ViewModel.Поиск по имени.Странное поведение при фильтрации - PullRequest
0 голосов
/ 09 марта 2019

Когда вы нажимаете на кнопку поиска, это активность с полным списком предметов.Вверху находится editText, и когда пользователь начинает вводить имя, список должен динамически фильтроваться.Я осваиваю только компоненты архитектуры, и мне кажется, что мне удалось реализовать поиск, но он работает криво.

Допустим, следующие имена: "магия", "лето", "соль", "искра" и т. Д.,Я начинаю набирать «s» - список меняется, остаются только слова с этой буквой.Затем я ввожу «а», слово «соль» должно остаться, но ничего не меняется.Когда я стираю напечатанный, список не обновляется.Помогите решить проблему.

DataDao

 @Query("SELECT * FROM Data WHERE title LIKE :search")
LiveData<List<Data>> getAllSearch(String search);

DataRepository

    public class DataRepository {
private DatabaseCopier db;
private DataDao dataDao;

DataRepository(Application application) {
    db = DatabaseCopier.getInstance(application);
    dataDao = db.getDatabase().dataDao();
}

LiveData<List<Data>> getAllSearch(String search) {
    return db.getDatabase().dataDao().getAllSearch(search);
}

ViewModel с фабрикой, где я передаю имя конструктору.

 public class DataViewModelSearch extends AndroidViewModel {
private LiveData<List<Data>> currentData;
private DataRepository repository;

public DataViewModelSearch(@NonNull Application application, final String dataTitle) {
    super(application);
    String verseTitle = dataTitle;
    repository = new DataRepositorySearch(application);
    currentData = repository.getAllSearch(verseTitle);
}

public LiveData<List<Data>> getAllSearch() {
    return currentData;
}

    public static class ModelFactorySearch extends ViewModelProvider.NewInstanceFactory {
        @NonNull
        private final Application application;
        private final String dataTitle;
        private final DataRepository repository;

        public ModelFactorySearch(@NonNull Application application, String title) {
            super();
            this.application = application;
            this.dataTitle = title;
            repository = new DataRepository(application);
        }

        @NonNull
        @SuppressWarnings("unchecked")
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            if (modelClass == DataViewModel.class) {
                return (T) new DataViewModelSearch(application, dataTitle);
            }
            return null;
        }
    }

}

SearchActivity

 public class SearchActivity extends AppCompatActivity {
private SearchAdapter adapter;
RvObserver observer;
EditText etFilter;
RecyclerView recyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    observer = new RvObserver();
    etFilter = findViewById(R.id.et_filter);
    recyclerView = findViewById(R.id.rv_search);

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);
    DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, LinearLayoutManager.VERTICAL);
    dividerItemDecoration.setDrawable(this.getResources().getDrawable(R.drawable.divider));
    recyclerView.addItemDecoration(dividerItemDecoration);
    adapter = new SearchAdapter(onSearchClickListener, this);
    recyclerView.setAdapter(adapter);
    DataListViewModel dataListViewModel = ViewModelProviders.of(this).get(DataListViewModel.class);
    dataListViewModel.getAllVersesABS().observe(this, new Observer<List<Data>>() {
        @Override
        public void onChanged(List<Data> data) {
            adapter.setData(data);
        }
    });

    Bundle bundle = new Bundle(1);
    bundle.putString("filter", "");


    etFilter.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            refresh(charSequence.toString());
        }

        @Override
        public void afterTextChanged(Editable editable) {

        }

    });
}


private void refresh(String searchText) {
    Bundle bundle = new Bundle(1);
    bundle.putString("filter", searchText);

    searchText = "%" + searchText + "%";
    final DataViewModelSearch.ModelFactorySearch factory = new DataViewModelSearch.ModelFactorySearch(
            getApplication(), searchText);

    final DataViewModelSearch modelSearch = ViewModelProviders.of(this, factory)
            .get(DataViewModelSearch.class);

    modelSearch.getAllSearch().observe(this, new Observer<List<Data>>() {
        @Override
        public void onChanged(List<Data> data) {
            adapter.setData(data);
            adapter.notifyDataSetChanged();
        }
    });

}

@Override
protected void onResume() {
    super.onResume();
    adapter.registerAdapterDataObserver(observer);
}

@Override
protected void onPause() {
    super.onPause();
    adapter.unregisterAdapterDataObserver(observer);
}

1 Ответ

0 голосов
/ 11 марта 2019

Во-первых, у вас проблема в логике обновления.Каждый раз, когда вы что-то печатаете, вы создаете новую ViewModel с новым репозиторием.

Во-вторых, вы используете LiveData в качестве асинхронного рабочего инструмента, но LiveData срабатывает, когда вы что-то изменяете в своей базе данных.Однако вы не меняете данные и просто хотите выполнить SQL-запрос.Вот почему я использую AsyncTask в качестве примера (для простоты).Вы можете использовать RxJava.

Вот простой пример.

SearchActivity

public class SearchActivity extends AppCompatActivity {
private SearchAdapter adapter;
private DataViewModelSearch dataListViewModel;
EditText etFilter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);
    etFilter = findViewById(R.id.et_filter);
    RecyclerView recyclerView = findViewById(R.id.rv_search);

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);
    adapter = new SearchAdapter(onSearchClickListener, this);
    recyclerView.setAdapter(adapter);

    dataListViewModel = ViewModelProviders.of(this).get(DataListViewModel.class);
    dataListViewModel.searchData.observe(this, new Observer<List<Data>>() {
        @Override
        public void onChanged(List<Data> data) {
            adapter.setData(data); // it will be triggered every time when we change searchData in ViewModel via searchData.setValue()
        }
    });

    etFilter.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            dataListViewModel.refresh(charSequence.toString());
        }

        @Override
        public void afterTextChanged(Editable editable) {

        }

    });
}
}    

ViewModel

public class DataViewModelSearch extends AndroidViewModel {

MutableLiveData<List<Data>> searchData = new MutableLiveData<>();

private DataRepository repository;

public DataViewModelSearch(@NonNull Application application) {
    super(application);
    repository = new DataRepositorySearch(application); // better create repos outside viewModel or activity, but this is for example
}

private void refresh(String searchText) {
    String formattedSearchText = "%" + searchText + "%";
    new GetSearchDataTask.execute(formattedSearchText)
}

//for Async Work
private class GetSearchDataTask extends AsyncTask<Void, Void, List<Data>> {

        @Override
        protected List<Data> doInBackground(String... params) {
            return repository.getAllSearch(params[0])
        }

        @Override
        protected void onPostExecute(List<Data> data) {
            super.onPostExecute(data); 
            searchData.setValue(data); //change LiveData value
        }
    }


}

Ваш репозиторий должен вернуть List<Data> getAllSearch(String search);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...