通过接口

时间:2017-01-06 15:00:29

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

片段是底部导航栏的一部分,到目前为止在导航部分非常好。但是当我尝试将数据从fragment1传递到fragment2时,应用程序崩溃了。此外,我正在使用谷歌在link

之后给出的示例

当我使用以下代码时,android studio会给我不推荐的警告!

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

所以我正在使用 CONTEXT 而不是 ACTIVITY ,这是我崩溃的代码:

MainActivity

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                                                                        过程:com.br.tron.bottombar,PID:3744                                                                        java.lang.NullPointerException:尝试调用虚方法' void com.br.tron.bottombar.StreamFragment.getUrl(java.lang.String)'在null对象引用上                                                                            在com.br.tron.bottombar.MainActivity.setUrl(MainActivity.java:64)                                                                            在com.br.tron.bottombar.RadioFragment.onClick(RadioFragment.java:61)                                                                            在android.view.View.performClick(View.java:5201)                                                                            在android.view.View $ PerformClick.run(View.java:21209)                                                                            在android.os.Handler.handleCallback(Handler.java:739)                                                                            在android.os.Handler.dispatchMessage(Handler.java:95)                                                                            在android.os.Looper.loop(Looper.java:148)                                                                            在android.app.ActivityThread.main(ActivityThread.java:5525)                                                                            at java.lang.reflect.Method.invoke(Native Method)                                                                            在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:730)                                                                            在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)   01-06 20:10:24.663 3744-3744 /? I /处理:发送信号。 PID:3744 SIG:9

3 个答案:

答案 0 :(得分:3)

您永远不会注册稍后搜索的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中的片段是否为StreamFragment。由于您为所有三种类型的自定义片段注册了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中的标记字符串中进行适当的更改:

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

答案 1 :(得分:0)

您应该在textViewStream片段中初始化StreamFragment

答案 2 :(得分:0)

目前的两个答案都关键在于您的崩溃问题。我希望这会照顾你的主要问题。 @asadmshah似乎已经解决了你的下一个问题。一定要投票给他的回答&接受它。

关于使用Google示例代码的警告,如果您告诉它创建一个新片段,AS将会提供给您。

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

这一点是为了确保您附加的Activity实现了您在片段中定义的界面。

关于界面的主题,所有片段到活动的通信应该通过它来完成。最好找到一种通过界面调用performStreamClick()的方法。 (我刚刚意识到我在几个月前开始的应用程序中犯了同样的错误,但现在才刚刚结束:)。

最后,只是一个FYI,您可以使用getActivity()获取片段的附加活动。

编辑: 1,它可能有助于查看您当前的代码。我会假设你或多或少都有阿萨德在他的回答中所做的。此外,预期的行为是什么?我相信您在RadioFragment中进行了选择,然后将其替换为StreamFragment。也就是说,两个片段都占据整个导航栏,它们不会同时存在。如果这是错的,请告诉我。

如果您仍然按照以前的顺序调用setUrl()performStreamClick(),那么您将获得null,因为您从未使用该名称创建过片段。您找不到尚未创建的片段。

如果没有实际设置它来自己测试它,我相信你需要做的是将url保存在setUrl()的全局变量中,然后在你的点击监听器中,将其传递给{{1当你创建它时。

请参阅您为此选择的链接中的“向片段发送消息”部分

StreamFragment

(显然,处理你的url字符串而不是示例中的int)

此外,在搜索应该存在的片段

时处理null并不是一个坏主意
        Bundle args = new Bundle();
        args.putInt(ArticleFragment.ARG_POSITION, position);
        newFragment.setArguments(args);