当另一个片段中的数据发生更改时,如何刷新一个片段中的 RecyclerView

Posted

技术标签:

【中文标题】当另一个片段中的数据发生更改时,如何刷新一个片段中的 RecyclerView【英文标题】:How to refresh RecyclerView in one fragment when data changed in another fragment 【发布时间】:2017-03-24 00:59:28 【问题描述】:

数据提交成功后,如何将本地数据库中的数据刷新到RecyclerView?我使用应用程序上的选项卡。 2nd-Tab函数提交数据,如果成功,数据将存储在localDB

localDB 上的数据我将在3rd-Tab 上展示。 但是会发生什么,我必须滑动1st-Tab,然后滑动到2nd-Tab,然后再滑动到我的localDB 上的新3rd-Tab 数据成功显示

如果2nd-Tab我提交数据,然后我刷到3rd-Tab,数据将不会出现在数据列表中。 如何让数据直接显示而不需要滑动到第一个1st-Tab然后到2nd-Tab3rd-Tab

MainActivity

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import com.bertho.gmyl.fragments.EngagedFragment;
import com.bertho.gmyl.fragments.RequestFragment;
import com.bertho.gmyl.fragments.SigninFragment;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity 

    private static final String TAG = MainActivity.class.getSimpleName();

    private Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.engine_main);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        //getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
    

    private void setupViewPager(ViewPager viewPager) 
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new SigninFragment(), "SIGN-IN");
        adapter.addFrag(new EngagedFragment(), "ENGAGED ID");
        adapter.addFrag(new RequestFragment(), "LOCATION");
        viewPager.setAdapter(adapter);
    

    class ViewPagerAdapter extends FragmentPagerAdapter 
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        public ViewPagerAdapter(FragmentManager manager) 
            super(manager);
        

        @Override
        public Fragment getItem(int position) 
            return mFragmentList.get(position);
        

        @Override
        public int getCount() 
            return mFragmentList.size();
        

        public void addFrag(Fragment fragment, String title) 
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        

        @Override
        public CharSequence getPageTitle(int position) 
            return mFragmentTitleList.get(position);
        
    


EngagedFragment(2nd-Tab)表单来保存数据

import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.bertho.gmyl.R;
import com.bertho.gmyl.model.Engaged;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.bertho.gmyl.realm.RealmHelper;

public class EngagedFragment extends Fragment implements View.OnClickListener 

    private static final String TAG = EngagedFragment.class.getSimpleName();

    private EditText nama, email, nohp;
    private Button btnSaveConnection;
    private DatabaseReference mFirebaseDatabase;
    private FirebaseDatabase mFirebaseInstance;
    private RelativeLayout mRoot;
    private View rootView;
    private String userId;
    private TextView lblNama, lblEmail, lblNohp;
    private RelativeLayout relativeLayout;

    private RealmHelper realmHelper;


    public EngagedFragment() 
        // Required empty public constructor
    

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 

        rootView = inflater.inflate(R.layout.fragment_engaged, container, false);

        realmHelper = new RealmHelper(getActivity());

        String appName = getResources().getString(R.string.app_name);

        loadLocalDB();

        nama = (EditText) rootView.findViewById(R.id.txtName);
        email = (EditText) rootView.findViewById(R.id.txtEmail);
        nohp = (EditText) rootView.findViewById(R.id.txtNoHp);

        lblNama = (TextView) rootView.findViewById(R.id.lblNameval);
        lblEmail = (TextView) rootView.findViewById(R.id.lblEmailval);
        lblNohp = (TextView) rootView.findViewById(R.id.lblNohpval);
        relativeLayout = (RelativeLayout) rootView.findViewById(R.id.panelLabelDetail);
        btnSaveConnection = (Button) rootView.findViewById(R.id.btnEngaged);


        mFirebaseInstance = FirebaseDatabase.getInstance();

        mFirebaseDatabase = mFirebaseInstance.getReference("tbl_engaged");

        mFirebaseInstance.getReference("titleapp").setValue(appName);

        mFirebaseInstance.getReference("titleapp").addValueEventListener(new ValueEventListener() 
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) 
                Log.e(TAG, "TITLE UPDATED FROM FIREBASE");
                String appTitle = dataSnapshot.getValue(String.class);
                ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(appTitle);
            

            @Override
            public void onCancelled(DatabaseError error) 
                Log.e(TAG, "FAILED TO READ TITLE FROM FIREBASE.", error.toException());
            
        );

        btnSaveConnection.setOnClickListener(this);

        return rootView;
    

    private void showSnack(String notify) 
        mRoot = (RelativeLayout) rootView.findViewById(R.id.frag_engaged);
        Snackbar snackbar = Snackbar.make(mRoot, notify, Snackbar.LENGTH_LONG);
        snackbar.show();
    

    public void onClick(View v) 

        if(v.getId() == R.id.btnEngaged) 

            String txtName = nama.getText().toString();
            String txtEmail = email.getText().toString();
            String txtNo = nohp.getText().toString();

            if(txtName.equals("") || txtName.isEmpty()) 
                showSnack("Name must filled");
                nama.requestFocus();
             else if (txtEmail.equals("") || txtEmail.isEmpty()) 
                showSnack("Email must filled");
                email.requestFocus();
             else if (txtNo.equals("") || txtNo.isEmpty()) 
                showSnack("No.HP must filled");
                nohp.requestFocus();
             else 
                createUser(txtName, txtEmail, txtNo);
                saveToLocalDB(txtName, txtEmail, txtNo);
            
        
    

    private void saveToLocalDB(String txtName, String txtEmail, String txtNo) 
        realmHelper.addEngaged(txtName, txtEmail, txtNo);
    

    private void loadLocalDB() 
        realmHelper.getAllData();
    

    private void createUser(String name, String email, String nohp) 
        userId = mFirebaseDatabase.push().getKey();
        Engaged user = new Engaged(name, email, nohp);
        mFirebaseDatabase.child(userId).setValue(user);
        addUserChangeListener();
    

    private void addUserChangeListener() 

        mFirebaseDatabase.child(userId).addValueEventListener(new ValueEventListener() 
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) 
                Engaged user = dataSnapshot.getValue(Engaged.class);

                if (user == null) 
                    Log.e(TAG, "ENGAGED DATA IS NULL");
                    return;
                

                Log.e(TAG, "ENGAGED DATA IS CHANGED!" + user.name + ", " + user.email);

                lblNama.setText(user.name);
                lblEmail.setText(user.email);
                lblNohp.setText(user.nohp);

                //relativeLayout.setVisibility(View.VISIBLE);

                nama.setText("");
                email.setText("");
                nohp.setText("");
            

            @Override
            public void onCancelled(DatabaseError error) 
                // Failed to read value
                Log.e(TAG, "FAILED TO READ USER", error.toException());
            
        );
    

RequestFragment (3rd-Tab) 显示 localDB

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.bertho.gmyl.R;
import com.bertho.gmyl.adapter.AdapterEngaged;
import com.bertho.gmyl.model.ModelEngaged;
import com.bertho.gmyl.realm.RealmHelper;

import java.util.ArrayList;

public class RequestFragment extends Fragment 

    private static final String TAG = "RequestFragment";
    private RecyclerView recyclerView;
    private View rootView;
    private ArrayList<ModelEngaged> data;
    private RealmHelper helper;

    public RequestFragment() 
        // Required empty public constructor
    

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 

        rootView =  inflater.inflate(R.layout.fragment_request, container, false);

        data = new ArrayList<>();
        helper = new RealmHelper(getActivity());

        recyclerView = (RecyclerView) rootView.findViewById(R.id.rvArticle);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        setRecyclerView();

        return rootView;
    

    public void setRecyclerView() 
        try 
            data = helper.findAllArticle();
         catch (Exception e) 
            e.printStackTrace();
        
        AdapterEngaged adapter = new AdapterEngaged(data, new AdapterEngaged.OnItemClickListener() 
            @Override
            public void onClick(ModelEngaged item) 
                Toast.makeText(getContext(), "LIST CLICKED", Toast.LENGTH_LONG).show();
            
        );
        recyclerView.setAdapter(adapter);
    

    @Override
    public void onResume() 
        super.onResume();
        try 
            data = helper.findAllArticle();
         catch (Exception e) 
            e.printStackTrace();
        
        setRecyclerView();
    



一切都很顺利,只是希望表单提交的时候可以显示数据,可以在3rd-Tab上直接查看

【问题讨论】:

试试这个,在活动中使用一个接口,每当您在第二个选项卡中提交时设置回调,并在活动中的回调方法中重新加载第三个片段的列表 Viewpager初始化后尝试在mainactivity oncreate方法中加入这一行:ViewPager.setOffscreenPageLimit(3); viewPager.setOffscreenPageLimit();无效 @BerthoJoris 你解决了这个问题吗? 还没有......我还在尝试这个解决方案***.com/questions/20412379/… 【参考方案1】:

试试这个,

在 EngagedFragment 中创建接口 说,

public interface SubmitListener 

    void onSubmit();


private SubmitListener onSubmitListener;

public void setSubmitListener(SubmitListener onSubmitListener)
        this.onSubmitListener = onSubmitListener;


public SubmitListener getOnSubmitListener()
        return onSubmitListener;

在 saveToLocalDB(...) 方法中

打电话

onSubmitListener.onSubmit();

在 MainActivity:

1) 更新以下语句:

public class MainActivity extends AppCompatActivity implements EngagedFragment.SubmitListener

2) 将您的 ViewPagerAdapter 适配器; 变量设为全局变量;

添加片段时:

EngagedFragment engagedFrag = new EngagedFragment();
adapter.addFrag(engagedFrag, "ENGAGED ID");

...
viewPager.setAdapter(adapter);

3) 设置适配器后添加此项

engagedFrag.setSubmitListener(this);

4) 重写 onSubmit() 方法并在该方法中尝试以下代码

if(viewPager != null)

    if(adapter != null)
        Fragment fragment = adapter.getItem(2);
        if(fragment != null)
            RequestFragment requestFragment = (RequestFragment) fragment;
            requestFragment.setRecyclerView();
        
    

【讨论】:

Hai @Raghavendra,当我尝试您的代码时,我发现单击按钮保存时强制关闭。错误java.lang.NullPointerException: Attempt to invoke interface method 'void com.bertho.gmyl.fragments.EngagedFragment$SubmitListener.onSubmit()' on a null object reference 也许我错过了什么。但是,当我检查时,数据已保存。只强制关闭我的应用程序。这是 MainActivity :pastebin.com/mnMVzkjr 这是 EngagedFragment :pastebin.com/bWgSGmuk 是啊.....完美的作品..... :) 谢谢@Raghavendra ...顺便说一句,如果我有另一个选项卡,比如说第五个选项卡,我必须再次覆盖 onSubmit 方法中的代码? @BerthoJoris 很高兴!这有帮助。我没有得到qsn伙计。你能改写一下你想在第 5 个标签中做什么吗? 谢谢@Raghavendra ...它运行良好。非常感谢【参考方案2】:

试试这个

mViewPager.setOffscreenPageLimit(0); 

如果这没有帮助,请检查下面的问题:

fragment refresh On Swip

关于:mViewPager.setOffscreenPageLimit(0); 这可能不起作用,因为我在@commonware 的答案之一中找到了以下内容:-

"ViewPager 是否需要至少 1 个屏幕外页面 Yes。如果我正确阅读了源代码,您应该会在 LogCat 中收到关于此的警告,例如:

Requested offscreen page limit 0 too small; defaulting to 1"

【讨论】:

是的..不适用于viewPager.setOffscreenPageLimit(0); 你试过链接答案了吗? 还没有……但我会在这之后尝试

以上是关于当另一个片段中的数据发生更改时,如何刷新一个片段中的 RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章

当sqlite android片段中的数据更改或删除时如何刷新recyclerview?

发生配置更改时如何不重置我的片段?

在方向更改时保留列表片段中的列表

更改选项卡时避免/防止片段刷新

InfoWindow中的Android Google地图摘要自动更新

如何刷新其活动的 MenuitemSelected 上的片段?