java - 非法状态异常 : Fragment null must be a public static class to be properly recreated from instance state

标签 java android android-fragments

我在谷歌地图的 map 中显示 fragment 时遇到以下问题,我需要在 Android API 24 上工作,如果它工作的话,就像以前的版本一样。 错误在 Fragment MapRestaurante 行中:
getFmMain().getSupportFragmentManager().beginTransaction().add(R.id.activitymap, mMapFragment).commit()

如果我使用这条线同样的问题:

getChildFragmentManager().beginTransaction().add(R.id.activitymap, mMapFragment).commit();

Android 监视器

> FATAL EXCEPTION: main
Process: com.jungle, PID: 4356
java.lang.IllegalStateException: Fragment null must be a public static class to be  properly recreated from instance state.
  at     android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:435)
  at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:420)
  at com.jungle.MapRestaurant.onCreateView(MapRestaurant.java:72)
  at android.support.v4.app.Fragment.performCreateView(Fragment.java:2080)
  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108)
  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)
  at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
  at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1638)
  at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:679)
  at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:166)
  at android.support.v4.view.ViewPager.populate(ViewPager.java:1240)
  at android.support.v4.view.ViewPager.populate(ViewPager.java:1088)
  at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:542)
  at com.jungle.MainActivity.Setup(MainActivity.java:167)
  at com.jungle.MainActivity.access$000(MainActivity.java:34)
  at com.jungle.MainActivity$1.onClick(MainActivity.java:61)
  at android.view.View.performClick(View.java:4756)
  at android.view.View$PerformClick.run(View.java:19749)
  at android.os.Handler.handleCallback(Handler.java:739)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:135)
  at android.app.ActivityThread.main(ActivityThread.java:5221)
  at java.lang.reflect.Method.invoke(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:372)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

关闭 MainActivity

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {

private ViewPager viewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    viewPager = (ViewPager) super.findViewById(R.id.viewpager);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    Button btnRestaurant = (Button) findViewById(R.id.btnRestaurant);
    btnRestaurant.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Setup(1);
        }
    });
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_camera) {
        // Handle the camera action
    } else if (id == R.id.nav_gallery) {

    } else if (id == R.id.nav_slideshow) {

    } else if (id == R.id.nav_manage) {

    } else if (id == R.id.nav_share) {

    } else if (id == R.id.nav_send) {

    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}


public void maphotel(View v){
    //Intent intent = new Intent(this,MapRestaurant.class);
    //startActivity(intent);
    Setup(2);
}
public void mapthingsdo(View v){
    //Intent intent = new Intent(this,MapRestaurant.class);
    //startActivity(intent);
    Setup(3);
}

public FrameLayout getFrameContainer(){
   FrameLayout fm = (FrameLayout) findViewById(R.id.fragment_container);
    return fm;
 }
private void Setup(int id){
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    switch (id){
        case 1:
            if(adapter.getmFragmentTitleList().size() > 0) {
                adapter.getmFragmentTitleList().clear();
            }

            adapter.addFragment(new MapRestaurant(this), null);
            adapter.notifyDataSetChanged();

            break;
        case 2:
            if(adapter.getmFragmentTitleList().size() > 0) {
                adapter.getmFragmentTitleList().clear();
            }
            adapter.addFragment(new MapHotel(this), null);
            adapter.notifyDataSetChanged();
            break;
        case 3:
            if(adapter.getmFragmentTitleList().size() > 0) {
                adapter.getmFragmentTitleList().clear();
            }
            adapter.addFragment(new MapThingstodo(this), null);
            adapter.notifyDataSetChanged();
            break;
    }

     viewPager.setAdapter(adapter);
 }


//Clase para visualizar los fragmentos y los tabs en el viewpager
class ViewPagerAdapter extends FragmentStatePagerAdapter {
    private List<Fragment> mFragmentList = new ArrayList<>();
    private  List<String> mFragmentTitleList = new ArrayList<>();

    public List<String> getmFragmentTitleList() {
        return mFragmentTitleList;
    }

    public List<Fragment> getmFragmentList() {
        return mFragmentList;
    }

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);

    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment, String title) {

        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);

    }

    @Override
    public CharSequence getPageTitle(int position) {

        return mFragmentTitleList.get(position);
    }

    //this is called when notifyDataSetChanged() is called
    @Override
    public int getItemPosition(Object object) {
        // refresh all fragments when data set changed
        return   POSITION_NONE;
    }


    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if (position >= getCount()) {
            FragmentManager manager = ((Fragment) object).getFragmentManager();
            FragmentTransaction trans = manager.beginTransaction();
            trans.remove((Fragment) object);
            trans.commit();

        }

    }

}

}

Fragment MapRestaturant

public class MapRestaurant extends Fragment implements OnMapReadyCallback {

private GoogleMap mMap;
private SupportMapFragment mMapFragment;
static Context contexto;
private MainActivity fmMain;
@SuppressLint("ValidFragment")
public MapRestaurant(MainActivity fmMain) {
    this.fmMain = fmMain;
}

public MainActivity getFmMain() {
    return fmMain;
}

public void setFmMain(MainActivity fmMain) {
    this.fmMain = fmMain;
}

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_maps, container, false);
mMapFragment = new SupportMapFragment() {
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);

        }
    };
contexto = v.getContext();
mMapFragment.getMapAsync(this);
//getChildFragmentManager().beginTransaction().add(R.id.activitymap, mMapFragment).commit();
 getFmMain().getSupportFragmentManager().beginTransaction().add(R.id.activitymap, mMapFragment).commit();//aqui es donde me tira el error

 return  v;
}

@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (ContextCompat.checkSelfPermission(contexto, Manifest.permission.ACCESS_COARSE_LOCATION)== PackageManager.PERMISSION_GRANTED) {
        mMap.setMyLocationEnabled(true);
    }

    mMap.addMarker(new MarkerOptions().position(new LatLng( -25.598303, -54.575627)).title("Angelo Resto Bar Restaurant")).setIcon(BitmapDescriptorFactory.fromResource(R.drawable.restaurant));
    mMap.addMarker(new MarkerOptions().position(new LatLng(  -25.598265, -54.575681)).title("Restaurante II Frantello")).setIcon(BitmapDescriptorFactory.fromResource(R.drawable.restaurant));
    mMap.addMarker(new MarkerOptions().position(new LatLng( -25.598806, -54.575069)).title("La Tata Restaurante")).setIcon(BitmapDescriptorFactory.fromResource(R.drawable.restaurant));
    mMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(-25.598806, -54.575069)));
    mMap.moveCamera(CameraUpdateFactory.zoomTo(9));
    mMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
        @Override
        public void onInfoWindowClick(Marker marker) {
            NotifPopUp firstFragment = new NotifPopUp();
            fmMain.getSupportFragmentManager().beginTransaction().add(getFmMain().getFrameContainer().getId(), firstFragment).commit();

        }
    });
    }
}

谢谢!!!

最佳答案

  1. 摆脱:

    @SuppressLint("ValidFragment")
    public MapRestaurant(MainActivity fmMain) {
        this.fmMain = fmMain;
    }
    
    public MainActivity getFmMain() {
       return fmMain;
    }
    
    public void setFmMain(MainActivity fmMain) {
         this.fmMain = fmMain;
    }
    

Android 会为您保留该引用。使用 getActivity()检索主机 Activity .同样的事情适用于 contexto = v.getContext(); .

  1. 改变

    getFmMain().getSupportFragmentManager()
    

getFragmentManager() .如果您确实导入了 Fragment来自支持库,在 Fragment 中的子类,getFragmentManager() , 返回 FragmentManager 的支持版本.不需要魔法

关于java - 非法状态异常 : Fragment null must be a public static class to be properly recreated from instance state,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39532999/

相关文章:

java - 未找到 Spark SQL 包

Fragment中Android getSupportFragmentManager NULL指针异常

android - 按下状态波纹效果+正常状态透明

java - 将项目添加到 Collection 夹数据库时更改图标颜色

Android 全屏 fragment 对话框错误

java - ViewPager、FragmentStatePagerAdapter、ListFragment单独列出每个Fragment的数据

java - 如何在数组中间添加?

Java、Postgres、Redis : PostConstruct not completely working?

java - Android Jellybean Activity 生命周期错误

java - 如何在Android中获取应用程序数据目录