android - fragment 之间通过接口(interface)进行通信

标签 android android-studio android-fragments android-fragmentactivity bottomnavigationview

fragment 是底部导航栏的一部分,到目前为止导航部分还不错。但是当我尝试将数据从 fragment1 传递到 fragment2 时,应用程序崩溃了。此外,我正在使用谷歌在以下 link 中给出的示例

当我使用以下代码时,android studio 会给我弃用警告!

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

所以我使用的是 CONTEXT 而不是 ACTIVITY 下面是我崩溃的代码:

主要 Activity

import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.br.tron.bottombar.RadioFragment;
import com.br.tron.bottombar.StreamFragment;
import com.br.tron.bottombar.InfoFragment;

public class MainActivity extends AppCompatActivity implements RadioFragment.OnNameSetListener {

    BottomNavigationView bottomNavigationView;
    private Fragment fragment;
    private FragmentManager fragmentManager;

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

        fragmentManager = getSupportFragmentManager();
        fragment = new RadioFragment();
        final FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.main_container, fragment).commit();

        bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomNavigationBar);
        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener(){
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {

                switch (item.getItemId()) {
                    case R.id.nav_button_one:
                        fragment = new RadioFragment();
                        break;
                    case R.id.nav_button_two:
                        fragment = new StreamFragment();
                        break;
                    case R.id.nav_button_three:
                        fragment = new InfoFragment();
                        break;
                }
                final FragmentTransaction transaction = fragmentManager.beginTransaction();
                transaction.replace(R.id.main_container, fragment).commit();
                return true;
            }
        });
    }

    public void performStreamClick(){
        View view = bottomNavigationView.findViewById(R.id.nav_button_two);
        view.performClick();
    }

    @Override
    public void setUrl(String url) {
        StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("frag");
        frag.getUrl(url);
    }
}

RadioFragment(数据存在的Fragment1)

import android.app.Activity;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

public class RadioFragment extends Fragment implements Button.OnClickListener  {

    Button buttonman;
    View rootView;
    String url;
    Activity a;
    OnNameSetListener onNameSetListener;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof Activity) {
            a = (Activity) context;
            try{
                onNameSetListener=(OnNameSetListener) context;
            }
            catch (Exception e){}
        }
    }

    public RadioFragment(){
    };

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

        rootView = inflater.inflate(R.layout.fragment_player, container, false);
        buttonman = (Button)rootView.findViewById(R.id.buttonman);
        buttonman.setOnClickListener(this);
        return rootView;
    }

    @Override
    public void onClick(View v) {
        /*Fragment fragment = new StreamFragment();
        FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.main_container, fragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();*/
        url="www.idontknow.com";
        onNameSetListener.setUrl(url);
        ((MainActivity)a).performStreamClick();
    }

    public interface OnNameSetListener
    {
        public void setUrl(String url);
    }
}

StreamFragment(fragment2 我想从 fragment1 发送数据)

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class StreamFragment extends Fragment {

    TextView textViewStream;

    public StreamFragment(){};

    @Override
    public View onCreateView(final LayoutInflater inflater,final ViewGroup container,final Bundle savedInstanceState) {
        return  inflater.inflate(R.layout.fragment_stream, container, false);

    }

    public void getUrl(String url)
    {
        textViewStream.setText(url);
    }

}

LOGCAT

01-06 20:10:23.023 3744-3744/com.br.tron.bottombar E/AndroidRuntime: FATAL EXCEPTION: main Process: com.br.tron.bottombar, PID: 3744 java.lang.NullPointerException: Attempt to invoke virtual method 'void com.br.tron.bottombar.StreamFragment.getUrl(java.lang.String)' on a null object reference at com.br.tron.bottombar.MainActivity.setUrl(MainActivity.java:64) at com.br.tron.bottombar.RadioFragment.onClick(RadioFragment.java:61) at android.view.View.performClick(View.java:5201) at android.view.View$PerformClick.run(View.java:21209) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5525) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 01-06 20:10:24.663 3744-3744/? I/Process: Sending signal. PID: 3744 SIG: 9

最佳答案

您永远不会注册您稍后搜索的 frag 标签。

在您的 MainActivity 中修改:

final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.main_container, fragment, "frag").commit();
...
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment, "frag").commit();
...

除了在您的 StreamFragment 类中,您永远不会在扩充布局后设置 TextViewStream 变量。

@Override
public View onCreateView(final LayoutInflater inflater,final ViewGroup container,final Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_stream, container, false);
    textViewStream = (TextView) view.findViewById(R.id.ID_GOES_HERE);
    return view;
}

编辑:更多错误

你得到一个 ClassCastException 因为你没有检查你在 MainActivity.setUrl 中得到的 fragment 是否是一个 StreamFragment .它失败是有道理的,因为您为所有三种类型的自定义 fragment 注册了 frag 标记。这是进一步的解决方案:

        fragment = new RadioFragment();
        final FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.main_container, fragment, "radio_fragment").commit();
        ...

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {

            switch (item.getItemId()) {
                String tag = "";
                case R.id.nav_button_one:
                    fragment = new RadioFragment();
                    tag = "radio_fragment";
                    break;
                case R.id.nav_button_two:
                    fragment = new StreamFragment();
                    tag = "stream_fragment";
                    break;
                case R.id.nav_button_three:
                    fragment = new InfoFragment();
                    tag = "info_fragment";
                    break;
            }
            final FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.replace(R.id.main_container, fragment, tag).commit();
            return true;
        }

setUrl 中的 Tag 字符串中进行适当的更改:

StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("stream_fragment");
if (frag != null) frag.getUrl(url);

关于android - fragment 之间通过接口(interface)进行通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41508340/

相关文章:

java - 如何在 android studio 中导入 javax.json.binding ?

android - 拉动刷新recyclerview android

android - Flutter 中的控制台消息

android - Android Studio Gradle连接被拒绝:连接

java - 如何在 Android Studio 的 ActionBar 上添加返回按钮?

android - 无法解析方法 createSpeechRecognizer()

android - 由于引用丢失, Activity 在方向更改时重新创建 fragment ,如何避免这种情况?

android - 在我的 apk 中保留 admob 广告单元 ID 是否不安全?

android - 如何在RecyclerView中实现定时自动滚动和位置标记?

android - android 中的 TileMap