Android 未连接到主机的片段
我来解释一下,以防万一。我正在使用底部导航视图和Jetpack的移动导航图等等。我重新实现了这个方法: NavigationUI.setupWithNavController(…) 在导航设置过程中,我没有使用此方法,而是做了一个非常类似的操作: customSetupWithNavController(…) 我所做的唯一更改是更改片段之间的默认淡入淡出过渡,并开始使用更自然(在我看来)的侧幻灯片动画,就像onNavDestinationSelected中的一样:Android 未连接到主机的片段,android,android-fragments,uinavigationcontroller,android-context,android-viewholder,Android,Android Fragments,Uinavigationcontroller,Android Context,Android Viewholder,我来解释一下,以防万一。我正在使用底部导航视图和Jetpack的移动导航图等等。我重新实现了这个方法: NavigationUI.setupWithNavController(…) 在导航设置过程中,我没有使用此方法,而是做了一个非常类似的操作: customSetupWithNavController(…) 我所做的唯一更改是更改片段之间的默认淡入淡出过渡,并开始使用更自然(在我看来)的侧幻灯片动画,就像onNavDestinationSelected中的一样: if(origin == 0)
if(origin == 0){
builder.setEnterAnim(R.anim.slide_in_from_right)
.setExitAnim(R.anim.slide_out_to_left)
.setPopEnterAnim(R.anim.slide_in_from_left)
.setPopExitAnim(R.anim.slide_out_to_right);
}else if(origin == 1){
builder.setEnterAnim(R.anim.slide_in_from_left)
.setExitAnim(R.anim.slide_out_to_right)
.setPopEnterAnim(R.anim.slide_in_from_right)
.setPopExitAnim(R.anim.slide_out_to_left);
}
其中origin表示传入片段的来源方向
它带来了一个问题:我的两个碎片需要一个晶圆厂来向回收器添加元素,而侧滑梯的过渡突然变得难看。所以我在MainActivity的布局中添加了一个FAB,只有在调用这两个片段时,逻辑才会显示FAB
我找不到一种很好的方法将click事件从活动传递到片段,因为我无法实例化片段,因为导航处理整个过程
所以,我所做的就是创建一个ViewHolder,因为我知道它可以经受住生命周期的变化。此视图持有者持有一个int,以及一个MutableLiveData,在MainActivity逻辑中,我将BottomNavigationView所选元素的当前选定id传递给int,并且仅当单击MainActivity的FAB时,live布尔值才设置为true。因此,在FragmentsonViewCreated()中,我向该布尔值添加了观察者,当该值设置为true,并且传递给ViewHolder的id与当前片段的id匹配时,布尔值设置为false,可以执行以下操作:
eventsNotificationHandler.getClickEvent().observe(requireActivity(), new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if(aBoolean && eventsNotificationHandler.getPositionId() == R.id.nav_contacts){
eventsNotificationHandler.setClickEvent(false);
//do something here
}
}
});
eventsNotificationHandler.getClickEvent().observe(requireActivity(), new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if(aBoolean && eventsNotificationHandler.getPositionId() == R.id.nav_contacts){
eventsNotificationHandler.setClickEvent(false);
Intent newContact = new Intent(previouslyDefinedContext, NewContactActivity.class);
startActivity(newContact);
requireActivity().overridePendingTransition(R.anim.slide_in_from_right,R.anim.slide_out_to_left);
}
}
});
eventsNotificationHandler.getClickEvent().observe(Requiresponsibility(),new Observer()){
@凌驾
更改后的公共void(布尔aBoolean){
if(aBoolean&&eventsNotificationHandler.getPositionId()==R.id.nav_联系人){
eventsNotificationHandler.setClickEvent(false);
//在这里做点什么
}
}
});
此notificationHandler是ViewHolder
到目前为止一切都很好,现在我可以:
1-在BottomNavigationView片段之间自由导航,FAB仅显示所需片段
2-随时在观察者中使用Log.d(…),并查看调试消息
3-吐司消息,我想在任何时候,仅当上下文参数在观察者外部初始化时,,如下所示:
eventsNotificationHandler.getClickEvent().observe(requireActivity(), new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if(aBoolean && eventsNotificationHandler.getPositionId() == R.id.nav_contacts){
eventsNotificationHandler.setClickEvent(false);
//do something here
}
}
});
eventsNotificationHandler.getClickEvent().observe(requireActivity(), new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if(aBoolean && eventsNotificationHandler.getPositionId() == R.id.nav_contacts){
eventsNotificationHandler.setClickEvent(false);
Intent newContact = new Intent(previouslyDefinedContext, NewContactActivity.class);
startActivity(newContact);
requireActivity().overridePendingTransition(R.anim.slide_in_from_right,R.anim.slide_out_to_left);
}
}
});
Toast.makeText(以前定义的上下文,“一些文本”,Toast.LENGTH_SHORT.show()
我做不到的:
1-随时启动活动,在观察者内部使用与之前相同的想法,仅在之前初始化上下文,在观察者外部,我能够启动意图,如下所示:
eventsNotificationHandler.getClickEvent().observe(requireActivity(), new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if(aBoolean && eventsNotificationHandler.getPositionId() == R.id.nav_contacts){
eventsNotificationHandler.setClickEvent(false);
//do something here
}
}
});
eventsNotificationHandler.getClickEvent().observe(requireActivity(), new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if(aBoolean && eventsNotificationHandler.getPositionId() == R.id.nav_contacts){
eventsNotificationHandler.setClickEvent(false);
Intent newContact = new Intent(previouslyDefinedContext, NewContactActivity.class);
startActivity(newContact);
requireActivity().overridePendingTransition(R.anim.slide_in_from_right,R.anim.slide_out_to_left);
}
}
});
eventsNotificationHandler.getClickEvent().observe(Requiresponsibility(),new Observer()){
@凌驾
更改后的公共void(布尔aBoolean){
if(aBoolean&&eventsNotificationHandler.getPositionId()==R.id.nav_联系人){
eventsNotificationHandler.setClickEvent(false);
Intent newContact=newintent(以前定义的上下文,NewContactActivity.class);
星触觉(新接触);
require responsibility().覆盖结束转换(R.anim.从右滑入,R.anim.滑出到左);
}
}
});
但在这种特殊情况下,我可以启动新活动任意次数,但只有当我直接导航到应用程序打开后定义观察者的特定片段时,如果我决定先通过其他片段导航,然后转到该片段尝试启动活动,应用程序崩溃了
我注意到,当我从观察者内部调用requireContext()时,会发生这种确切的行为,它可以工作,但随后停止工作
应用程序因以下原因崩溃:
E/AndroidRuntime:致命异常:主
流程:cu.arrowtech.bpawreckproject,PID:18019
java.lang.IllegalStateException:片段碎片联系人{883259b}(9f127bdb-127d-4366-b90b-c8900a5a771e)}未附加到活动
我想要什么:
1-如果可能的话,通过在MainActivity中按FAB键,从片段内部启动新活动的正确方法
2-如果一个可能的解决方案意味着改变我已有的逻辑,那么这是一个切换片段的好方法
3-继续使用Jetpack和导航图
我可以通过在每个片段中使用两个独立的晶圆厂来做我想做的事情,但是转换并不漂亮
我愿意接受建议,即使这意味着要改变逻辑。我几乎可以肯定,这一定是一种更好的方式来完成我正在做的事情,而不是为此使用ViewHolder
我想得到一个类似谷歌支付的东西,似乎是添加支付方式、通行证和转账的按钮是同一个按钮,但它适应每种情况。经过一些研究,我确实找到了一种方法,可以在片段和移动导航组件之间保持流畅的过渡,并在主活动布局中保持单个晶圆厂 我所做的是使用界面而不是ViewModels(我一直知道这种方法是错误的): 因此,在我的MainActivity中,我将该接口定义为null,并根据情况创建了一个方法来定义它。我的主要活动如下:
public class MainActivity extends AppCompatActivity {
//UI elements
private FloatingActionButton main_fab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Same dode to get the custom animations
//.......
//Main and only Fab configuration
main_fab = findViewById(R.id.main_fab);
main_fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(sharedViewsInterface !=null){
sharedViewsInterface.onFabClicked();
}
}
});
}
//Other auxiliary methods
public void setInterface(SharedViewsInterface sharedViewsInterface){
this.sharedViewsInterface = sharedViewsInterface;
}
}
通过这样做,我可以从每个片段实现onCreate中的接口:
((MainActivity) requireActivity()).setInterface(new SharedViewsInterface() {
@Override
public void onFabClicked() {
Intent newContact = new Intent(requireContext(), NewContactActivity.class);
startActivity(newContact);
requireActivity().overridePendingTransition(R.anim.slide_in_from_right_short,R.anim.slide_out_to_left_medium);
}
});
这很有效,因为只有在具有接口实现的片段可见时才会显示FAB,请参见我的示例gif
请注意,