1

The fragments are a part of the bottom navigation bar, so far so good on the navigation part. But when i try to pass data from fragment1 to fragment2 the app is crashing. Also I am using the example given by google at this following link

When I use the following code android studio gives me deprecated warning!

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

So I am using CONTEXT instead of ACTIVITY below is my code that crashes :

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 where the data exist)

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 where I want to send the data -from 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

4

3 回答 3

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;
}

编辑:进一步的错误

你得到 a 是ClassCastException因为你没有检查你进入的片段是否MainActivity.setUrl是 a 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);
于 2017-01-06T15:11:12.237 回答
1

当前的两个答案都与您的崩溃问题有关。我希望这会解决您的主要问题。@asadmshah 似乎已经解决了您的下一个问题。确保对他的答案进行投票并接受。

关于使用谷歌示例代码的警告,如果你告诉它创建一个新片段,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()通过接口调用的方法。(我刚刚意识到我在几个月前开始的应用程序上犯了同样的错误,但现在才刚刚完成:)。

最后,仅供参考,您可以使用getActivity().

编辑:第一,查看您当前的代码可能会有所帮助。我将假设您或多或少地了解了 Asad 在他的回答中提出的内容。另外,预期的行为是什么?我相信您在 中进行了选择,RadioFragment然后将其替换为StreamFragment. 也就是说,两个片段都占据了整个导航栏,它们不会同时存在。如果这是错误的,请告诉我。

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

在没有实际设置它自己进行测试的情况下,我相信您需要做的是将 url 保存在全局变量中setUrl(),然后在您的点击侦听器中,将其传递给StreamFragment您创建它时。

请参阅您为此设置的链接的“向片段传递消息”部分

        Bundle args = new Bundle();
        args.putInt(ArticleFragment.ARG_POSITION, position);
        newFragment.setArguments(args);

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

此外,在搜索应该已经存在的片段时处理 null 也不是一个坏主意

    StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("stream_frag");
    if(frag == null) {
        final FragmentTransaction transaction = fragmentManager.beginTransaction();
        StreamFragment fragment = new StreamFragment();
        transaction.replace(R.id.main_container, fragment, "stream_frag").commit();
    }          
于 2017-01-06T15:45:28.583 回答
0

您应该textViewStreamStreamFragment片段中初始化您的。

于 2017-01-06T15:08:05.750 回答