You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android OPC UA客户端多PLC连接时SessionFragment子Fragment加载失败

Android OPC UA客户端多会话子Fragment加载异常问题

我首次在网上求助,平时自己能找到解决方案,但这次实在定位不了问题。我正在开发Android平台的OPC UA客户端,需要实现同时连接多个PLC的功能。

MainActivity中包含一个FragmentContainerView,用于承载代表单个PLC会话的SessionFragment;每个SessionFragment又由FragmentContainerView和BottomNavigationView组成,即一个PLC连接对应一个SessionFragment实例。

连接第二个PLC时出现异常:SessionFragment中的FragmentContainerView无法加载子Fragment。第一个会话能正常显示子Fragment,但第二个会话的FragmentContainerView始终为空。我通过调试器和日志确认,第二个会话中fragmentmanager.begintransaction.add(...).show(...).commit();语句已执行,且后续没有隐藏该Fragment的操作。默认进入会话时仅显示第一个子Fragment,其余子Fragment添加时会被隐藏,但第二个会话的子Fragment就是无法加载。我已经按照Commonsware的建议将FrameLayout替换为FragmentContainerView。

应用流程

  • 启动应用时,FragmentContainerView显示连接Fragment
  • 点击按钮后,根据输入的IP地址发现端点
  • 点击端点并连接成功后,创建SessionFragment。该SessionFragment包含FragmentContainerView和BottomNavigationView,会初始化三个子Fragment:SessionConnected、Dashboard、Browse

相关代码

MainActivity布局文件

<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawerlayout"
tools:background="@color/darkblue_primary"
>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <com.google.android.material.appbar.MaterialToolbar
        android:layout_width="match_parent"
        android:layout_height="56dp"
        app:title="OPC UA Client"
        android:id="@+id/actionbar"
        android:elevation="4dp"
        app:navigationIcon="@drawable/baseline_menu_24"
        app:navigationIconTint="@color/white"
        android:background="@color/darkblue_secondary"
        />
    <LinearLayout
        android:id="@+id/ly_tabs"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:orientation="horizontal"
        android:visibility="gone"
        android:background="@color/darkblue_secondary"
        tools:visibility="visible">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_sessionTabs"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            tools:layout_weight="1"
            android:scrollbars="none"
            />

        <ImageView
            android:id="@+id/iv_addSessionTabs"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            app:srcCompat="@drawable/baseline_add_24"
            android:background="@drawable/ripple_effect_secondary_round"/>
    </LinearLayout>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fc_MainActivity"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        app:layout_constraintBottom_toTopOf="@+id/bnv_Session"
        app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>

<RelativeLayout
    android:id="@+id/rl_MainActivity"
    android:layout_width="300dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="@color/darkblue_primary">

    <include layout="@layout/layout_drawer" />
</RelativeLayout></androidx.drawerlayout.widget.DrawerLayout>

连接成功时的代码

SessionElement sessionElement = (SessionElement) msg.obj;
successfulDialog.show();
connectionLoadingDialog.dismiss();
AuthDialog.dismiss();
int session_id = sessionTabsList.size();;
String sessionID = sessionElement.getSession().getSession().getSessionId().getValue().toString();
sessionTabsList = sendDataToActivity.UpdateSessionList();

if(sessionTabsList == null)
{
    sessionTabsList = new ArrayList<>();
}

String session_name = "Session "+ session_id;
SessionTabs newsession = new SessionTabs(session_name,sessionID,endpoints[position].getEndpointUrl());
newsession.setCurrentSession(session_id);
newsession.setSelected(true);
sessionTabsList.add(newsession);
sendDataToActivity.SendToActivity(sessionTabsList);

result.putString("session_id",sessionID);
result.putString("session_name",session_name);
result.putParcelable("SessionElement",sessionElement);

Session_fragment sessionFragment = new Session_fragment();
sessionFragment.setArguments(result);
hideConnectionFragment();
fragmentManager.beginTransaction().add(R.id.fc_MainActivity,sessionFragment,sessionID)
        .show(sessionFragment)
        .commit();

SessionFragment布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@color/darkblue_primary"
android:orientation="vertical"
>

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/fc_session"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:visibility="visible"
    android:background="@color/white"
    app:layout_constraintBottom_toTopOf="@+id/bnv_Session"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bnv_Session"
    android:layout_width="match_parent"
    android:layout_height="70dp"
    android:background="@color/darkblue_secondary"
    android:visibility="visible"
    app:itemActiveIndicatorStyle="@style/Base.Theme.Client_OPC_UA"
    app:itemIconSize="30dp"
    app:itemIconTint="@drawable/colorselect"
    app:itemTextColor="@drawable/colorselect"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/fc_session"
    app:menu="@menu/btmnav_menu" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline21"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.92" /></LinearLayout>

SessionFragment代码

public class Session_fragment extends Fragment {
BottomNavigationView bottomNavigationView,bnv_Dashboard;
FragmentManager fragmentManager;
Bundle bundle;
SessionElement sessionElement;
String session_id;
String session_name;
Dialog loadingDialog;
Dialog errorDialog;
TextView errorMessage,errorTitle;
String session_Connected, dashboard, browse,dashboard_Liste,dashboard_Diagram;
Session_connected sessionConnected;
Dashboard_fragment dashboard_fragment;
Dashboard_List_fragment dashboard_list_fragment;
Dashboard_Diagram_fragment dashboardDiagramFragment;
Browse_fragment browseFragment;
FragmentContainerView frameLayout;

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

    
    View view = inflater.inflate(R.layout.layout_session, container, false);
    fragmentManager= getParentFragmentManager();
    bundle= getArguments();
    if(bundle!=null)
    {
        session_name=bundle.getString("session_name");
        session_id=bundle.getString("session_id");
        sessionElement = bundle.getParcelable("SessionElement");
    }
    frameLayout=view.findViewById(R.id.fc_session);
    frameLayout.setVisibility(View.VISIBLE);
    InitializeLoadingDialog();
    InitializeErrorDialog();
   
    session_Connected = "Session_Connected"+ session_id;
    dashboard = "Dashboard"+ session_id;
    browse = "Browse"+ session_id;
    dashboard_Liste = "Dashboard_Liste" + session_id;
    dashboard_Diagram = "Dashboard_Diagram" + session_id;

    bottomNavigationView = view.findViewById(R.id.bnv_Session);
    bottomNavigationView.setVisibility(View.VISIBLE);
    bottomNavigationView.setOnItemSelectedListener(item -> {
        if (item.getItemId() == R.id.Session && bottomNavigationView.getSelectedItemId()!=R.id.Session) {

            manageFragmentTransaction(R.id.Session);
        }
        if (item.getItemId() == R.id.Dashboard && bottomNavigationView.getSelectedItemId()!=R.id.Dashboard) {

            manageFragmentTransaction(R.id.Dashboard);
        }
        if (item.getItemId() == R.id.Browse && bottomNavigationView.getSelectedItemId()!=R.id.Browse) {
            manageFragmentTransaction(R.id.Browse);
        }
        return true;
    });

    CreateSubscription();

    CreateDashboardFragment();
    CreateBrowseFragment();
    CreateSessionConnectFragment();
    return view;
}

private void CreateSessionConnectFragment() {
    Session_connected sessionConnected = new Session_connected();
    bundle.putParcelable("SessionElement",sessionElement);
    sessionConnected.setArguments(bundle);
    fragmentManager.beginTransaction().add(R.id.fc_session, sessionConnected, session_Connected).commit();
    Log.d("FRAGMENT "+session_name, "Creating Session_Connected");
    Log.d("FRAGMENT "+session_name, "Showing Session_Connected");
}

private void CreateBrowseFragment() {
    Browse_fragment browseFragment = new Browse_fragment();
    bundle.putParcelable("SessionElement",sessionElement);
    browseFragment.setArguments(bundle);
    fragmentManager.beginTransaction().add(R.id.fc_session, browseFragment, browse).hide(browseFragment).commit();
    Log.d("FRAGMENT "+session_name, "Creating BrowseFragment");
}
private void CreateDashboardFragment() {
    Dashboard_fragment dashboardFragment = new Dashboard_fragment();
    bundle.putParcelable("SessionElement",sessionElement);
    dashboardFragment.setArguments(bundle);
    fragmentManager.beginTransaction().add(R.id.fc_session, dashboardFragment, dashboard).hide(dashboardFragment).commit();
    Log.d("FRAGMENT "+session_name, "Creating DashboardFragment");
}

内容的提问来源于stack exchange,提问作者Noctis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 22:00:54