过滤后的列表更改后如何维护RecyclerView过滤列表和主列表?

时间:2018-03-28 09:13:36

标签: android filter android-recyclerview

我有一个ArrayList,其中填充了

  

1)主要活动我的主要数据家

     

2)内部的recyclerview适配器

     

3)过滤列表

我有一个问题,当我搜索一些字符串时返回过滤后的数据。我实现更新该数据,但是当我更新该数据并刷新时,我获得了新的更新数据。但后来我从字符串中删除了一个字符并显示旧数据。

就像我搜索“ app ”一样,我的过滤数据会在RecyclerView数据中显示“ application ”和“ apple ”。

我将“ apple ”更新为“ applered ” 反对后,我的RecyclerVeiw向我展示了“ aaplication ”和“ aaplered ” 这没关系。
从字符串“ ap ”中删除一个字符后,我的RecyclerView显示旧的“应用程序”和“ apple ”。

那意味着我的数据没有更新所有列表?如何将数据更新更新为所有三个列表?

1 个答案:

答案 0 :(得分:1)

其他人可能会给你更好的建议,但我认为你应该通过viewmodel类扩展ViewModel(或者需要上下文,AndroidViewModel)。在本课程中,您可以编写搜索算法代码。

您可以使用LiveDataMutableLiveData。列出所有项目,然后将MutableLiveData项添加到与搜索匹配的项目中。从搜索字符串中删除字符时,您重做搜索并将所有找到的项目添加到MutableLiveData

最后,观察LiveData中的更改,并在更改时更新适配器。

编辑示例:

ViewModel类

public class MyModelSupplier extends AndroidViewModel{

//if you do not need application or context in your coustructor, class can extend ViewModel

private MutableLiveData<List<MyModel>> myModelList;
private List<myModel> nonVisibleMyModelList;
private Context context;

//Constructor
//if you do not need application or context in your coustructor, class can extend ViewModel
public MyModelSupplier(@NonNull Application application) {
    super(application);
    this.context = application.getApplicationContext();
    updateFullList();
}

LiveData<List<MyModel>> getMyModelList() {
    //this stuff is the one observed by the activity
    if (MyModelList == null) {
        MyModelList = new MutableLiveData<>();
        updateFullList();
    }
    return MyModelList;
} 

void searchMyModelListByName(final String itemName) {

    if (itemName == null) {
        MyModelList.setValue(nonVisibleMyModelList);
    } else {
        new ApplicationFilterQueryTask(searchString).execute();
    }

}


//update
private void updateFullList() { new fullListQueryTask().execute(); }
class fullListQueryTask extends AsyncTask<Void, Void, List<MyModel> > {

    @Override
    protected void onPostExecute(List<MyModel> myRetrievedModelObjects) {
        MyModelList.setValue(myRetrievedModelObjects);
        nonVisibleMyModelList = myRetrievedModelObjects;
        super.onPostExecute(myRetrievedModelObjects);
    }

    @Override
    protected List<MyModel> doInBackground(Void... voids) {

        List<MyModel> myHiddenButFoundModelObjects = new ArrayList<>();
        //gather all your stuff in here (full list))

        //return stuff in alphabetical order
        java.util.Collections.sort(installedPackages, new MyModelNameComparator());
        return installedPackages;
    }
}

//so that they can be sorted
protected class MyModelNameComparator implements Comparator<MyModel> {
    @Override
    public int compare(MyModel o1, MyModel o2) {
        //getName() should be implemented in your MyModel
        return accentedToAsci(o1.getName()).compareToIgnoreCase(accentedToAsci(o2.getName()));
    }
}


class ApplicationFilterQueryTask extends AsyncTask<Void, Void, List<MyModel> > {

    private final String searchString;

    ApplicationFilterQueryTask(String searchString) { this.searchString = searchString;}

    @Override
    protected void onPostExecute(List<MyModel> myFilteredModelList) {
        MyModelList.setValue(myFilteredModelList);
        super.onPostExecute(myFilteredModelList);
    }

    @Override
    protected List<MyModel> doInBackground(Void... voids) {

        List<MyModel> searchResult = new ArrayList<>();

        //this is where the filtering occurs
        for (MyModel model : nonVisibleMyModelList) {
            if (accentedToAsci(model.getName().toLowerCase()).contains(accentedToAsci(searchString).toLowerCase())) {
                searchResult.add(model);
            }
        }

        return searchResult;
    }
}

}

在主要活动OnCreate中,你做了所有正常的事情,但是像这样填充recyclerView:

MyModelSupplier  = ViewModelProviders.of(this).get(MyModelSupplier.class);
    MyModelSupplier .getMyModelList().observe(this, packageSummaryList -> {

        adapter = new MyRecyclerViewAdapter(// stuff here for the constructor, or you can update the old one as well);
        recyclerView.setAdapter(adapter);
    });

你的主动活动应该延伸

AppCompatActivity implements SearchView.OnQueryTextListener,

你应该实现这样的方法(注意你需要菜单资源来获得按钮 - 如果你不知道如何添加菜单资源就谷歌这个)

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_items, menu);
    MenuItem menuItem = menu.findItem(R.id.menu_search);
    SearchView searchView = (SearchView)menuItem.getActionView();
    searchView.setQueryHint(getString(R.string.menu_search_tooltip));
    searchView.setOnQueryTextListener(this);

    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onQueryTextSubmit(String query) {
    return false;
}

@Override
public boolean onQueryTextChange(String newText) {

    MyModelSupplier.searchMyModelListByName(newText);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.menu_settings) {
        startActivity(new Intent(this, ActivitySettings.class));
        return true;
    }
    return super.onOptionsItemSelected(item);
}       

此外,这段代码可能会警告你内存泄漏,但我还没有弄明白如何在没有此警告的情况下在asynctask中运行与上下文相关的内容。

如果您遇到困难或成功,请告诉我。