androidfragment到fragment通讯:通过接口更新ReceiverFragment的recyclerView [英] android fragment to fragment communication : update recyclerView of the ReceiverFragment via interface

查看:50
本文介绍了androidfragment到fragment通讯:通过接口更新ReceiverFragment的recyclerView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个片段,我正在尝试通过接口更新ReceiverFragment的recyclerView.这两个片段都有自己的适配器(SenderAdapter和ReceiverAdapter).

不得不提到的是,我还有两个SQLDatabase,其中group.db用于填充SenderFragment,client.db用于填充ReceiverFragment.

但是只有在SenderAdapter中选中一个复选框时,才会填充ReceiverFragment.

片段之间的所有通信都可以.当我勾选一个复选框时,SenderAdapter将一条消息发送给MainActivity,而MainActivity将同一条消息发送给ReceiverFragment.

这是SenderFragment:

这将是理想的结果.

当我使用接口中的消息读取client.db时,会得到nullException.

这是ReceiverFragment:

public class ReceiverFragment extends Fragment {

    View view;
    private RecyclerView mClientList;
    private RecyclerView.Adapter mClientListAdapter;
    private RecyclerView.LayoutManager mClientListLayoutManager;

    private String receivedFromSender;

    ArrayList<ClientObject> clientList;

    SQLiteDatabase clientListTable;
    ClientRepository clientRepository;


    private static String rootPath = Environment.getExternalStorageDirectory()+"/PassKeyBF/";


    public ReceiverFragment() {
        // Required empty public constructor
    }

    public String getMessageFromSender(String message){
        if (message != null) {
            receivedFromSender = message;
            Log.i("debinf recfrag", "message from sender (function) is : " + receivedFromSender);

            //Log.i("debinf recgfrag", "mContext in interface : " + mContext);

            if (message != null) {
                if (new File(rootPath + receivedFromSender, "client.db").isFile()) {
                    clientReading(message);
                }
            }                                  


        }

        return null;

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        view = inflater.inflate(R.layout.fragment_receiver, container, false);

        // If I use mContext instead of getContext(), I get rid of the context error showed below.
        //mContext = getContext();

        clientList = new ArrayList<>();

        initializeRecyclerView();
        //clientReading("-LWBPaM7RA9UOcUVty79");

        return view;
    }

    private void clientReading(String pathToClientTable) {

        if (new File(rootPath + pathToClientTable, "client.db").isFile()) {

            Log.i("debinf recgfrag", "mContext in clientReading" + mContext);

            ClientDatabaseHelper clientDatabaseHelper = new ClientDatabaseHelper(mContext,"client.db", rootPath+pathToClientTable+"/");

            clientListTable = clientDatabaseHelper.getReadableDatabase();
            clientRepository = new ClientRepository(clientListTable);

            clientList = clientRepository.SearchAllClients();
            Log.i("debinf recfrag", "clientList in clientReading is " + clientList.get(0).getName());
            mClientListAdapter = new ReceiverAdapter(mContext,clientList);
            mClientList.setAdapter(mClientListAdapter);
            //mClientListAdapter.notifyDataSetChanged();

        }

    }

    private void initializeRecyclerView() {

        mClientList = (RecyclerView) view.findViewById(R.id.clientList);
        mClientList.setNestedScrollingEnabled(false);
        mClientList.setHasFixedSize(false);
        mClientListLayoutManager = new LinearLayoutManager(mContext,LinearLayout.VERTICAL,false);
        mClientList.setLayoutManager(mClientListLayoutManager);

        mClientListAdapter = new ReceiverAdapter(mContext,clientList);
        mClientList.setAdapter(mClientListAdapter);

    }

}

这是ReceiverAdapter

public class ReceiverAdapter extends RecyclerView.Adapter<ReceiverAdapter.ReceiverViewHolder> {

    ArrayList<ClientObject> clientList;
    Context mContext;

    private ReceiverAdapter adapter;

    public ReceiverAdapter(Context mContext, ArrayList<ClientObject> clientList) {
        this.clientList = clientList;
        this.mContext = mContext;
    }

    @NonNull
    @Override
    public ReceiverViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_callcenter_client, null, false);

        RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutView.setLayoutParams(lp);

        ReceiverViewHolder rcv = new ReceiverViewHolder(layoutView);
        return rcv;
    }

    @Override
    public void onBindViewHolder(@NonNull ReceiverViewHolder holder, int position) {

        holder.mName.setText(clientList.get(position).getName());
        holder.mPhone.setText(clientList.get(position).getPhone());

    }

    @Override
    public int getItemCount() {
        return clientList.size();
    }

    public class ReceiverViewHolder extends RecyclerView.ViewHolder {

        public TextView mName, mPhone;
        //public LinearLayout mLayout;

        public ReceiverViewHolder(@NonNull View itemView) {
            super(itemView);

            mName = (TextView) itemView.findViewById(R.id.client_name);
            mPhone = (TextView) itemView.findViewById(R.id.client_phone);
            //mLayout = (LinearLayout) itemView.findViewById(R.id.layoutItemClient);
        }
    }
}

编辑

我更改了ReceiverFragment,使其更易于理解.

那是我使用getContext()时遇到的致命错误.我根本无法与我的SQLDatabase建立连接.

2019-01-31 15:41:45.118 22318-22318/com.example.aliton.passkeybetweenfrags E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.aliton.passkeybetweenfrags, PID: 22318
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:352)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:322)
        at com.example.aliton.passkeybetweenfrags.ReceiverFragment.clientReading(ReceiverFragment.java:104)
        at com.example.aliton.passkeybetweenfrags.ReceiverFragment.getMessageFromSender(ReceiverFragment.java:53)
        at com.example.aliton.passkeybetweenfrags.MainActivity.getMessage(MainActivity.java:64)
        at com.example.aliton.passkeybetweenfrags.SenderAdapter$1.onCheckedChanged(SenderAdapter.java:54)
        at android.widget.CompoundButton.setChecked(CompoundButton.java:171)
        at android.widget.CompoundButton.toggle(CompoundButton.java:127)
        at android.widget.CompoundButton.performClick(CompoundButton.java:132)
        at android.view.View.performClickInternal(View.java:6574)
        at android.view.View.access$3100(View.java:778)
        at android.view.View$PerformClick.run(View.java:25885)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

现在,当我抑制getContext()并将其在mContext中设为静态时.我可以与SQLDatabase建立连接,但是由于ReceiverAdapter:

2019-01-31 15:35:05.541 21936-21936/com.example.aliton.passkeybetweenfrags E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.aliton.passkeybetweenfrags, PID: 21936
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setAdapter(android.support.v7.widget.RecyclerView$Adapter)' on a null object reference
        at com.example.aliton.passkeybetweenfrags.ReceiverFragment.clientReading(ReceiverFragment.java:110)
        at com.example.aliton.passkeybetweenfrags.ReceiverFragment.getMessageFromSender(ReceiverFragment.java:53)
        at com.example.aliton.passkeybetweenfrags.MainActivity.getMessage(MainActivity.java:64)
        at com.example.aliton.passkeybetweenfrags.SenderAdapter$1.onCheckedChanged(SenderAdapter.java:54)
        at android.widget.CompoundButton.setChecked(CompoundButton.java:171)
        at android.widget.CompoundButton.toggle(CompoundButton.java:127)
        at android.widget.CompoundButton.performClick(CompoundButton.java:132)
        at android.view.View.performClickInternal(View.java:6574)
        at android.view.View.access$3100(View.java:778)
        at android.view.View$PerformClick.run(View.java:25885)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

读取SQLDatabase(client.db)或更新ReceiverAdapter时出现错误.

这是应用程序主文件夹的链接:

https://1drv.ms/u/s!AjteqjTsJm9qgn6kODT9OJmMcY4e

这是指向SQLDatabase(group.db和client.db)的链接

https://1drv.ms/u/s!AjteqjTsJm9qgn_L52cz3lDWOOWe

解决方案

我终于找到了答案.

整个问题都发生在MainActivity中.我正在像这样从MainActivity到ReceiverFragment进行通信:

ReceiverFragment receiverFragment = new ReceiverFragment();

并发送如下消息:

   @Override
    public void getMessage(String message) {

        receiverFragment.getMessageFromSender(message);

    }

该消息通常是从MainActivity传递到ReceiverFragment的,但是我收到了ReceiverFragment的recyclerView的NullPointerException.

通过使用以下方式将消息传递到ReceiverFragment(此链接中的答案

代码和SQLDatabase的链接(group.db和client.db)仍然可以下载.

对于像我这样开始使用Android并对代码感兴趣的用户,请不要忘记在MainActivity中更改传递功能.

谢谢大家,祝你好运!

I have two fragments and I am trying to update the recyclerView of the ReceiverFragment via interface. Both fragments have its own adapter (SenderAdapter and ReceiverAdapter).

I have to mention that I also have two SQLDatabase, where group.db is used to populate the SenderFragment and client.db is used to populate the ReceiverFragment.

But ReceiverFragment will only be populate if a CheckBox is ticked in the SenderAdapter.

All the communication between the fragments is ok. When I tick a CheckBox, The SenderAdapter sends a message to MainActivity and the MainActivity sends the same message to ReceiverFragment.

This is SenderFragment:

This would be the desired result.

When I use the message from interface to read the client.db, I get the nullException.

This is the ReceiverFragment:

public class ReceiverFragment extends Fragment {

    View view;
    private RecyclerView mClientList;
    private RecyclerView.Adapter mClientListAdapter;
    private RecyclerView.LayoutManager mClientListLayoutManager;

    private String receivedFromSender;

    ArrayList<ClientObject> clientList;

    SQLiteDatabase clientListTable;
    ClientRepository clientRepository;


    private static String rootPath = Environment.getExternalStorageDirectory()+"/PassKeyBF/";


    public ReceiverFragment() {
        // Required empty public constructor
    }

    public String getMessageFromSender(String message){
        if (message != null) {
            receivedFromSender = message;
            Log.i("debinf recfrag", "message from sender (function) is : " + receivedFromSender);

            //Log.i("debinf recgfrag", "mContext in interface : " + mContext);

            if (message != null) {
                if (new File(rootPath + receivedFromSender, "client.db").isFile()) {
                    clientReading(message);
                }
            }                                  


        }

        return null;

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        view = inflater.inflate(R.layout.fragment_receiver, container, false);

        // If I use mContext instead of getContext(), I get rid of the context error showed below.
        //mContext = getContext();

        clientList = new ArrayList<>();

        initializeRecyclerView();
        //clientReading("-LWBPaM7RA9UOcUVty79");

        return view;
    }

    private void clientReading(String pathToClientTable) {

        if (new File(rootPath + pathToClientTable, "client.db").isFile()) {

            Log.i("debinf recgfrag", "mContext in clientReading" + mContext);

            ClientDatabaseHelper clientDatabaseHelper = new ClientDatabaseHelper(mContext,"client.db", rootPath+pathToClientTable+"/");

            clientListTable = clientDatabaseHelper.getReadableDatabase();
            clientRepository = new ClientRepository(clientListTable);

            clientList = clientRepository.SearchAllClients();
            Log.i("debinf recfrag", "clientList in clientReading is " + clientList.get(0).getName());
            mClientListAdapter = new ReceiverAdapter(mContext,clientList);
            mClientList.setAdapter(mClientListAdapter);
            //mClientListAdapter.notifyDataSetChanged();

        }

    }

    private void initializeRecyclerView() {

        mClientList = (RecyclerView) view.findViewById(R.id.clientList);
        mClientList.setNestedScrollingEnabled(false);
        mClientList.setHasFixedSize(false);
        mClientListLayoutManager = new LinearLayoutManager(mContext,LinearLayout.VERTICAL,false);
        mClientList.setLayoutManager(mClientListLayoutManager);

        mClientListAdapter = new ReceiverAdapter(mContext,clientList);
        mClientList.setAdapter(mClientListAdapter);

    }

}

This is the ReceiverAdapter

public class ReceiverAdapter extends RecyclerView.Adapter<ReceiverAdapter.ReceiverViewHolder> {

    ArrayList<ClientObject> clientList;
    Context mContext;

    private ReceiverAdapter adapter;

    public ReceiverAdapter(Context mContext, ArrayList<ClientObject> clientList) {
        this.clientList = clientList;
        this.mContext = mContext;
    }

    @NonNull
    @Override
    public ReceiverViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_callcenter_client, null, false);

        RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutView.setLayoutParams(lp);

        ReceiverViewHolder rcv = new ReceiverViewHolder(layoutView);
        return rcv;
    }

    @Override
    public void onBindViewHolder(@NonNull ReceiverViewHolder holder, int position) {

        holder.mName.setText(clientList.get(position).getName());
        holder.mPhone.setText(clientList.get(position).getPhone());

    }

    @Override
    public int getItemCount() {
        return clientList.size();
    }

    public class ReceiverViewHolder extends RecyclerView.ViewHolder {

        public TextView mName, mPhone;
        //public LinearLayout mLayout;

        public ReceiverViewHolder(@NonNull View itemView) {
            super(itemView);

            mName = (TextView) itemView.findViewById(R.id.client_name);
            mPhone = (TextView) itemView.findViewById(R.id.client_phone);
            //mLayout = (LinearLayout) itemView.findViewById(R.id.layoutItemClient);
        }
    }
}

EDIT

I changed the ReceiverFragment so that it could be more understandable.

That's the FATAL ERROR I get when I use the getContext(). I simply cannot make a connection with my SQLDatabase.

2019-01-31 15:41:45.118 22318-22318/com.example.aliton.passkeybetweenfrags E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.aliton.passkeybetweenfrags, PID: 22318
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:352)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:322)
        at com.example.aliton.passkeybetweenfrags.ReceiverFragment.clientReading(ReceiverFragment.java:104)
        at com.example.aliton.passkeybetweenfrags.ReceiverFragment.getMessageFromSender(ReceiverFragment.java:53)
        at com.example.aliton.passkeybetweenfrags.MainActivity.getMessage(MainActivity.java:64)
        at com.example.aliton.passkeybetweenfrags.SenderAdapter$1.onCheckedChanged(SenderAdapter.java:54)
        at android.widget.CompoundButton.setChecked(CompoundButton.java:171)
        at android.widget.CompoundButton.toggle(CompoundButton.java:127)
        at android.widget.CompoundButton.performClick(CompoundButton.java:132)
        at android.view.View.performClickInternal(View.java:6574)
        at android.view.View.access$3100(View.java:778)
        at android.view.View$PerformClick.run(View.java:25885)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Now, when I suppress getContext() and make it static in mContext. I can make a connection with SQLDatabase, but I get this FATAL error because the ReceiverAdapter:

2019-01-31 15:35:05.541 21936-21936/com.example.aliton.passkeybetweenfrags E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.aliton.passkeybetweenfrags, PID: 21936
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setAdapter(android.support.v7.widget.RecyclerView$Adapter)' on a null object reference
        at com.example.aliton.passkeybetweenfrags.ReceiverFragment.clientReading(ReceiverFragment.java:110)
        at com.example.aliton.passkeybetweenfrags.ReceiverFragment.getMessageFromSender(ReceiverFragment.java:53)
        at com.example.aliton.passkeybetweenfrags.MainActivity.getMessage(MainActivity.java:64)
        at com.example.aliton.passkeybetweenfrags.SenderAdapter$1.onCheckedChanged(SenderAdapter.java:54)
        at android.widget.CompoundButton.setChecked(CompoundButton.java:171)
        at android.widget.CompoundButton.toggle(CompoundButton.java:127)
        at android.widget.CompoundButton.performClick(CompoundButton.java:132)
        at android.view.View.performClickInternal(View.java:6574)
        at android.view.View.access$3100(View.java:778)
        at android.view.View$PerformClick.run(View.java:25885)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

I can either get an error while reading the SQLDatabase (client.db) or while updating the ReceiverAdapter.

This is the link for the Main folder of the app:

https://1drv.ms/u/s!AjteqjTsJm9qgn6kODT9OJmMcY4e

This is the link to the SQLDatabase (group.db and client.db)

https://1drv.ms/u/s!AjteqjTsJm9qgn_L52cz3lDWOOWe

解决方案

I finally found an answer.

The whole problem happened in the MainActivity. I was communicating from the MainActivity to the ReceiverFragment like this :

ReceiverFragment receiverFragment = new ReceiverFragment();

And sending the message like this:

   @Override
    public void getMessage(String message) {

        receiverFragment.getMessageFromSender(message);

    }

The message was been passed from MainActivity to ReceiverFragment normally, But I was getting a NullPointerException for the recyclerView of the ReceiverFragment.

The problem was solved by using the following way to deliver the message to the ReceiverFragment (answer found in this link https://www.journaldev.com/14207/android-passing-data-between-fragments):

@Override
    public void getMessage(String message) {

        String tag = "android:switcher:" + R.id.tabs_pager + ":" + 1;
        ReceiverFragment rf = (ReceiverFragment) getSupportFragmentManager().findFragmentByTag(tag);
        rf.getMessageFromSender(message);

    }

The links for the code and the SQLDatabase (group.db and client.db) are still available for download.

For those who are starting in Android like me and interested in the code, please do not forget to change the delivering function in the MainActivity.

Thank you all and good luck!

这篇关于androidfragment到fragment通讯:通过接口更新ReceiverFragment的recyclerView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆