片段是底部导航栏的一部分,到目前为止在导航部分非常好。但是当我尝试将数据从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
答案 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);