【问题标题】:RealmRecyclerView updates only after switching between tabs. Empty view appears with delayRealmRecyclerView 仅在选项卡之间切换后更新。空视图出现延迟
【发布时间】:2018-01-11 13:36:14
【问题描述】:

ViewPager 3 页 (FragmentPagerAdapter) RealmRecyclerView 在第一页。

Realm 为空时,表示“No items”消息和“Add”按钮。没关系。

所以,我已将我的第一个对象添加到 Realm。 EmptyView 仍然在这里,但我预计会看到 RealmRecyclerView (RRV)。

当我在 tab1tab2 之间切换时,没有任何变化。 但是如果我切换到tab3,然后回到我的tab1 - RRV 终于出现了。 它不依赖于页面的内容。 RRV 的外观仅受 tab3 的返回影响。

我不明白原因。 我重新检查了我的TabViewPagerTabAdapterFragments。 一切正常。 没有什么多余的,我认为这可能会影响这一点。

第二个问题

当我通过SearchView 的查询过滤我的RRV 时,小部件 EmptyView 出现延迟。

例如:如果有“12345”项,则 EmptyView 仅在查询为“1234567”而不是“123456”时出现..

Аt 第一个不匹配的RRV 仍然可见,尽管它是空的。 并且仅当两个或多个字符 RRV 的差异消失时。 去除多余的字符也不能给出正确的表示。

我认为这两种情况都有一个原因。 你能指出错误吗?

FirstFragment.java

public class FirstFragment extends Fragment {

Realm realm;
RecyclerView realmRecyclerView;
FirstAdapter adapter;
TextView emptyText;
Button buttonAdd;

public FirstFragment () {
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setHasOptionsMenu(true);
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View fragmentView = inflater.inflate(R.layout.fragment_first, container, false);
    realm = Realm.getDefaultInstance();
    realmRecyclerView = fragmentView.findViewById(R.id.recyclerView_first);

    RealmResults<Object> results = realm.where(Object.class).findAll();

    emptyText = fragmentView.findViewById(R.id.tv_no_data);
    buttonAdd = fragmentView.findViewById(R.id.button_add);

    setUpRealmRecyclerView();
    initButtonAdd();

    if (!results.isEmpty()) {
        realmRecyclerView.setVisibility(View.VISIBLE);
        emptyText.setVisibility(View.GONE);
        buttonAdd.setVisibility(View.GONE);

    } else {

        realmRecyclerView.setVisibility(View.GONE);
        emptyText.setVisibility(View.VISIBLE);
        buttonAdd.setVisibility(View.VISIBLE);
    }

    return fragmentView;
}

private void setUpRealmRecyclerView() {
    adapter = new FirstAdapter(realm, realm.where(Object.class).findAll());
    realmRecyclerView.setHasFixedSize(true);
    realmRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    realmRecyclerView.setAdapter(adapter);

    FirstTouchHelper callback = new FirstTouchHelper(realm);
    ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
    touchHelper.attachToRecyclerView(realmRecyclerView);
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    realmRecyclerView.setAdapter(null);
    realm.close();
}

private void initButtonAdd() {

//create new object dialog

}

@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
    inflater.inflate(R.menu.actionbar_menu, menu);

    SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
    final SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
    SearchableInfo searchableInfo = searchManager.getSearchableInfo(getActivity().getComponentName());
    searchView.setSearchableInfo(searchableInfo);
    searchView.setIconifiedByDefault(true);

    EditText editTextSearch = (EditText) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);

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

        @Override
        public void onTextChanged(CharSequence charSequence, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            adapter.getFilter().filter(editable);

            if (adapter.getItemCount()==0) {
                realmRecyclerView.setVisibility(View.GONE);
                buttonAdd.setVisibility(View.VISIBLE);

            } else {
                realmRecyclerView.setVisibility(View.VISIBLE);                    
                buttonAdd.setVisibility(View.GONE);
            }
        }
    });

    super.onCreateOptionsMenu(menu, inflater);
}

}

RRV 适配器:

public class FirstAdapter
    extends RealmRecyclerViewAdapter<Object, RecyclerView.ViewHolder>
    implements Filterable{

Realm realm;

public FirstAdapter(Realm realm, OrderedRealmCollection<Object> data) {
    super(data, true, true);
    this.realm = realm;
    setHasStableIds(true);
}

@Override
public long getItemId(int index) {
    return getItem(index).getId();
}

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

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    Object object = getData().get(position);
    ObjectClass classHolder = (ObjectClass) holder;
    classHolder.name.setText(object.getName());

}

public void filterResults(String text) {
    text = text == null ? null : text.toLowerCase().trim();
    RealmQuery<Object> query = realm.where(Object.class);

    if (text == null || "".equals(text)) {
        updateData(query
                .findAll()
                .sort("name"));
    } else {
        updateData(query
                .contains("name", text, Case.INSENSITIVE)
                .findAll()
                .sort("name"));
        }
}


public Filter getFilter() {
    ObjectFilter filter = new ObjectFilter(this);
    return filter;
}


private class ObjectFilter
        extends Filter {
    private final FirstAdapter adapter;

    private ObjectFilter(FirstAdapter adapter) {
        super();
        this.adapter = adapter;
    }

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        return new FilterResults();
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        adapter.filterResults(constraint.toString());
    }
}



private class ObjectClass
        extends RecyclerView.ViewHolder {
    TextView name;

    private ObjectClass(View itemView) {
        super(itemView);

        name = itemView.findViewById(R.id.name_text_view);
    }
}

}

【问题讨论】:

    标签: android android-recyclerview android-viewpager realm android-tablayout


    【解决方案1】:

    The reason why clicking the 3rd tab then clicking the 1st tab "reloads" and shows your views properly is because the offscreenPageLimit by default is 1, so when tab 1 is selected, tab 3 is destroyed,当tab 3被选中时,tab 1被销毁。

    所以你的视图被重新创建,所以它会正确显示。

    但要解决您的问题,您应该使用 RealmChangeListener 在写入 Realm 时接收通知。

    public class FirstFragment extends Fragment {
    
        Realm realm;
        RealmResults<Object> results;
        RealmChangeListener<RealmResults<Object>> changeListener = new RealmChangeListener<RealmResults<Object>>() {
            @Override
            public void onChange(RealmResults<Object> results) {
                if (!results.isEmpty()) {
                    realmRecyclerView.setVisibility(View.VISIBLE);
                    emptyText.setVisibility(View.GONE);
                    buttonAdd.setVisibility(View.GONE);
    
                } else {
    
                    realmRecyclerView.setVisibility(View.GONE);
                    emptyText.setVisibility(View.VISIBLE);
                    buttonAdd.setVisibility(View.VISIBLE);
                }
            }
        };
    
        RecyclerView realmRecyclerView;
        PickProductAdapter adapter;
        TextView emptyText;
        Button buttonAdd;
    
        public FirstFragment () {
        }
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setHasOptionsMenu(true);
        }
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View fragmentView = inflater.inflate(R.layout.fragment_first, container, false);
            realm = Realm.getDefaultInstance();
            realmRecyclerView = fragmentView.findViewById(R.id.recyclerView_first);
    
            results = realm.where(Object.class).findAllAsync();
            results.addChangeListener(changeListener);
    
            emptyText = fragmentView.findViewById(R.id.tv_no_data);
            buttonAdd = fragmentView.findViewById(R.id.button_add);
    
            setUpRealmRecyclerView();
            initButtonAdd();
    
    
            return fragmentView;
        }
    
        private void setUpRealmRecyclerView() {
            adapter = new PickProductAdapter(realm, results);
            realmRecyclerView.setHasFixedSize(true);
            realmRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
            realmRecyclerView.setAdapter(adapter);
    
            FirstTouchHelper callback = new FirstTouchHelper(realm);
            ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
            touchHelper.attachToRecyclerView(realmRecyclerView);
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            results.removeAllChangeListeners();
            realmRecyclerView.setAdapter(null);
            realm.close();
        }
    
        private void initButtonAdd() {
    
        //create new object dialog
    
        }
    
        @Override
        public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
            inflater.inflate(R.menu.first_actionbar_menu, menu);
    
            // set searchview
        }
    
    }
    

    编辑:您的空视图不更新的原因是因为它独立于适配器中的内容,因此您需要添加一些可以在过滤器处于活动状态时调用的回调方法。

    public class FirstFragment extends Fragment {
        ...
        public void updateData(RealmResults<Object> results) {
             if(this.results != null && this.results.isValid()) {
                 this.results.removeAllChangeListeners();
             }
             this.results = results;
             results.addChangeListener(changeListener);
        }
    

    public class FirstAdapter
        extends RealmRecyclerViewAdapter<Object, RecyclerView.ViewHolder>
        implements Filterable{
    
    FirstFragment firstFragment; // could be interface or somethin'
    Realm realm;
    
    public FirstAdapter(FirstFragment firstFragment, Realm realm, OrderedRealmCollection<Object> data) {
        ...
    
    ...
    
    @Override
    public void updateData(OrderedRealmCollection<Object> collection) {
        super.updateData(collection);
        firstFragment.updateData((RealmResults<Object>)collection);
    }
    

    编辑:

    还有

    RealmQuery<Object> query = realm.where(Object.class);
    
    if (text == null || "".equals(text)) {
        updateData(query
                .sort("name")
                .findAllAsync());
    } else {
        updateData(query
                .contains("name", text, Case.INSENSITIVE)
                .sort("name")
                .findAllAsync());
        }
    

    editTextSearch.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }
    
        @Override
        public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
    
        }
    
        @Override
        public void afterTextChanged(Editable editable) {
            adapter.getFilter().filter(editable);
    
            // this should be in `onChange()`
            /*if (adapter.getItemCount()==0) {
                realmRecyclerView.setVisibility(View.GONE);
                buttonAdd.setVisibility(View.VISIBLE);
    
            } else {
                realmRecyclerView.setVisibility(View.VISIBLE);                    
                buttonAdd.setVisibility(View.GONE);
            }*/
        }
    });
    

    【讨论】:

    • 我认为onDestroy() 没有被调用,但onDestroyView() 可能是。 FragmentPager 分离并重新附加片段。
    • 嗯,但我的 TabAdapter 扩展了 FragmentPagerAdapter,其中不调用 onDestroy。所以我认为问题出在别的地方。虽然是真的!他重新创建了片段,这就足够了(重写评论,无法使用@联系)
    • 标签问题已解决!谢谢!但是过滤还是不正确
    • 您的问题中没有与 SearchView 相关的代码,也没有关于它的设置或其他任何内容,真的
    • 但是adapter.getFilter().filter(editable);实际上是如何过滤的呢?显示您的适配器代码
    猜你喜欢
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2014-10-15
    相关资源
    最近更新 更多