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

Android配置变更后Activity恢复时Fragment重叠问题求助

配置变更后Activity恢复时Fragment重叠问题排查

我的Android应用包含一个Activity和一个Fragment,配置变更(比如横竖屏切换)后Activity恢复时,会创建两个Fragment并出现重叠现象,我没有使用ViewPager,看过相关问题但没理解解决方案,附上关键代码求排查线索。

ContinuarInformeActivity 关键代码

public class ContinuarInformeActivity extends AppCompatActivity  {
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_continuar_informe);

        // get fragment manager

        myChildToolbar =
                findViewById(R.id.toolbarinf);
        setSupportActionBar(myChildToolbar);
        // Get a support ActionBar corresponding to this toolbar
        ActionBar ab = getSupportActionBar();

        // Enable the Up button
        ab.setDisplayHomeAsUpEnabled(true);
        // add
        nviewModel =
                new ViewModelProvider(this).get(NuevoinformeViewModel.class);

     
        loadData(savedInstanceState);
        //reviso si es edicion y ya tengo info en temp
        ultimares=dViewModel.getUltimoTemp();

        if(ultimares!=null) //is edition
        {
            preguntaAct=dViewModel.inftempToReac(ultimares);

         
             if(preguntaAct.getTabla().equals(ultimares.getTabla())){
                //si es la misma

                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
               
                Bundle args = new Bundle();
                args.putInt(DetalleProductoFragment.ARG_PREGACT,preguntaAct.getId() );
                args.putBoolean(DetalleProductoFragment.ARG_ESEDI,true);
                DetalleProductoFragment nvofrag = new DetalleProductoFragment();
                nvofrag.setArguments(args);

                ft.add(R.id.continf_fragment,nvofrag);
                
               
                 ft.commit();

            }else{
                 buscarPreguntas();

                 dViewModel.getReactivos().observe(this, new Observer<List<Reactivo>>() {
                     @Override
                     public void onChanged(List<Reactivo> reactivos) {
                         Log.d(TAG, "reactivo:" + reactivos.get(0).getLabel());
                         Bundle args = new Bundle();
                         args.putInt(DetalleProductoFragment.ARG_PREGACT,reactivos.get(0).getId() );
                         args.putBoolean(DetalleProductoFragment.ARG_ESEDI,false);
                         DetalleProductoFragment nvofrag = new DetalleProductoFragment();
                         nvofrag.setArguments(args);
                         FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                       
                         ft.add(R.id.continf_fragment, nvofrag);

                         ft.commit();
                     }
                 });
            }
        }else {
            //is new
            buscarPreguntas();
          
            dViewModel.getReactivos().observe(this, new Observer<List<Reactivo>>() {
                @Override
                public void onChanged(List<Reactivo> reactivos) {
                    Log.d(TAG, "2reactivo:" + reactivos.get(0).getLabel());
                    Bundle args = new Bundle();
                    args.putInt(DetalleProductoFragment.ARG_PREGACT,reactivos.get(0).getId() );
                    args.putBoolean(DetalleProductoFragment.ARG_ESEDI,false);
                    DetalleProductoFragment nvofrag = new DetalleProductoFragment();
                    nvofrag.setArguments(args);
                    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
               
                    ft.add(R.id.continf_fragment, nvofrag);

                    ft.commit();
                }
            });
        }
    }

     public void loadData(Bundle savedInstanceState) {
        Bundle datosRecuperados = getIntent().getExtras();

        if(datosRecuperados!=null) {
            idinformeSel = datosRecuperados.getInt(INFORMESEL); //es la visita id
          
        }else { //lo recupero
        
            if (savedInstanceState != null) {    // Restore value of members from saved state
                Constantes.CLAVEUSUARIO = savedInstanceState.getString(KEY_USUARIO);
                Constantes.ETAPAACTUAL = savedInstanceState.getInt(KEY_ETAPAACT);
               Constantes.INDICEACTUAL=savedInstanceState.getString(KEY_INDICEACT);
              
                    Intent intento1 = new Intent(this, NavigationDrawerActivity.class);
                    startActivity(intento1);
                    finish();
                  
                    return;
            }

        }

        mBinding.setSdf(Constantes.sdfsolofecha);
       ....

    }

     @Override
    public boolean onSupportNavigateUp() {
        onBackPressed();
        return false;
    }
    boolean salir;
    @Override
    public void onBackPressed() {
       

      
        DetalleProductoFragment fragment = (DetalleProductoFragment) getSupportFragmentManager().findFragmentById(R.id.continf_fragment);
        numpreg = fragment.getNumPregunta();
       
       

        salir=true;
  
      
        if(numpreg==4||numpreg==3||numpreg==5||numpreg==43||numpreg==7)
        {
            return; //no puedo regresar
        }
       
        DetalleProductoFragment fragment = (DetalleProductoFragment) getSupportFragmentManager().findFragmentById(R.id.continf_fragment);
       fragment.atras();
        return;

        
    }

     @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_continuar, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        noSalir=false;
        switch (item.getItemId()) {
            case R.id.csalir:
                int numpreg=0;
                
                if(nviewModel.clienteSel==4)
                    if(numpreg==3||numpreg==4||numpreg==5){
                        noSalir=true;
                    }
                if(nviewModel.clienteSel==5||nviewModel.clienteSel==7)
                    if(numpreg==53||numpreg==54||numpreg==55){
                        noSalir=true;
                    }
                if(nviewModel.clienteSel==6)
                    if(numpreg==73||numpreg==74||numpreg==75){
                        noSalir=true;
                    }

                 

                return true;

            default:
                break;
        }

        return false;
    }
  

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {



        // Always call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putInt(KEY_ETAPAACT,Constantes.ETAPAACTUAL );
        savedInstanceState.putString(KEY_USUARIO, Constantes.CLAVEUSUARIO );
        savedInstanceState.putString(KEY_INDICEACT, Constantes.INDICEACTUAL );

        savedInstanceState.putInt("visitasel",idinformeSel );
    }
    }

DetalleProductoFragment 关键代码

public class DetalleProductoFragment extends Fragment {

    ...
    public DetalleProductoFragment() {

    }


    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
     
    }
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        mViewModel =
                new ViewModelProvider(requireActivity()).get(NuevoinformeViewModel.class);
      
        root = inflater.inflate(R.layout.fragment_generic2, container, false);
        

            svprin = root.findViewById(R.id.fgllcontentmain);

         

        return root;
    }

 

   


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
      
        if ((requestCode == REQUEST_CODE_TAKE_PHOTO) && resultCode == RESULT_OK) {
       

            if (archivofoto!=null&&archivofoto.exists()) {
                if(requestCode == REQUEST_CODE_TAKE_PHOTO) {
                   
                    preguntaview.setTextoint(nombre_foto);

                    if(ComprasUtils.getAvailableMemory(getActivity()).lowMemory)
                    {
                        Toast.makeText(getActivity(), "No hay memoria suficiente para esta accion", Toast.LENGTH_SHORT).show();

                        return;
                    }else {
                        // Bitmap bitmap1 = BitmapFactory.decodeFile(getActivity().getExternalFilesDir(null) + "/" + nombre_foto);
                        ComprasUtils cu = new ComprasUtils();
                        cu.comprimirImagen(archivofoto.getAbsolutePath());
                        Bitmap bitmap1 = ComprasUtils.decodeSampledBitmapFromResource(archivofoto.getAbsolutePath(), 100, 100);
                        preguntaview.setImageBitmap(bitmap1);
                        // fotomos.setLayoutParams(new LinearLayout.LayoutParams(350,150));
                        preguntaview.verBtnRotar();

                        nombre_foto=null;
                        archivofoto=null;
                        if(preguntaview.getNopermiso()!=null) {
                            preguntaview.getNopermiso().setChecked(false);
                        }
                        preguntaview.aceptarSetEnabled(true);
                    }

                }


            }
            else{
                Log.e(TAG,"Algo salió mal???");
            }


        }  
    @Override
    public void onDestroy() {

        super.onDestroy();


        if(sspeechRecognizer!=null)
            sspeechRecognizer.destroy();
    }
   
    @Override
    public void onPause() {
        super.onPause();


    }
  



    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putString("picUri", nombre_foto);
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        if(savedInstanceState!=null)
            nombre_foto= savedInstanceState.getString("picUri");
    }

  

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mViewModel = null;
        lcviewModel = null;
        dViewModel=null;
        preguntaview=null;

        tomadoDe=null;
        atributos=null;
        causas=null;
        root=null;

        preguntaAct=null;

        svprin=null;

        loadingDialog=null ;


        lcviewModel=null;
        nombre_foto=null;
        archivofoto=null;
    }

 

}

问题原因及修复方案

核心原因

Android系统在配置变更时,会自动保存并恢复FragmentManager中的Fragment实例。你的onCreate方法没有判断savedInstanceState是否为null,每次重建Activity都会重新执行Fragment的添加逻辑,导致系统恢复的旧Fragment和你新创建的Fragment重叠。

具体修复步骤

  1. 在Activity的onCreate中添加状态判断
    在执行Fragment添加逻辑前,先检查savedInstanceState是否为null。如果不为null,说明系统已经恢复了之前的Fragment,不需要再创建新的:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_continuar_informe);
        // ... 其他初始化代码 ...
        loadData(savedInstanceState);
        ultimares=dViewModel.getUltimoTemp();
    
        // 关键判断:仅当savedInstanceState为null时才创建Fragment
        if (savedInstanceState == null) {
            if(ultimares!=null) //is edition
            {
                preguntaAct=dViewModel.inftempToReac(ultimares);
                if(preguntaAct.getTabla().equals(ultimares.getTabla())){
                    // ... 原有的Fragment添加代码 ...
                }else{
                    buscarPreguntas();
                    dViewModel.getReactivos().observe(this, new Observer<List<Reactivo>>() {
                        @Override
                        public void onChanged(List<Reactivo> reactivos) {
                            // ... 原有的Fragment添加代码 ...
                        }
                    });
                }
            }else {
                //is new
                buscarPreguntas();
                dViewModel.getReactivos().observe(this, new Observer<List<Reactivo>>() {
                    @Override
                    public void onChanged(List<Reactivo> reactivos) {
                        // ... 原有的Fragment添加代码 ...
                    }
                });
            }
        }
    }
    
  2. 可选方案:使用replace替代add
    如果业务需要每次重建都创建新Fragment,可以用ft.replace(R.id.continf_fragment, nvofrag)替代ft.add,这样会移除容器中已有的Fragment,避免重叠。但这种方式会丢失之前Fragment的状态,仅适合不需要保留状态的场景。

  3. 验证Fragment状态恢复逻辑
    确保Fragment在onViewStateRestored中正确恢复状态,避免系统恢复的Fragment出现异常显示。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 09:09:56