Reputation: 752
My App crashes upon orientation change. I have taken care of following the default advice when this happens, namely that each fragment has a parameter-free constructor and, since I have implemented the Fragments inside my MainActivity, they are declared static. Yet I still face the same Exception as if I hadn't done so.
public class MainActivity extends FragmentActivity {
public static final String URL = "url";
public static final String ID = "id";
private SettingsPageAdapter pageAdapter;
private ViewPager pager;
private FrameLayout layoutTabBar;
public static class SettingsPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragments;
public SettingsPageAdapter(FragmentManager fm) {
super(fm);
fragments = new ArrayList<Fragment>();
}
public void addWebViewItem(String url, String id) {
final Fragment settingsFragment = new SettingsWebView();
final Bundle bundle = new Bundle();
bundle.putString(URL, url);
bundle.putString(ID, id);
settingsFragment.setArguments(bundle);
this.fragments.add(settingsFragment);
}
public void addItem(Fragment f, String id) {
final Bundle bundle = new Bundle();
bundle.putString(ID, id);
f.setArguments(bundle);
this.fragments.add(f);
}
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
@Override
public int getCount() {
return this.fragments.size();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.bar, new BarFragment()).commit();
}
pageAdapter = new SettingsPageAdapter(getSupportFragmentManager());
pageAdapter.addWebViewItem("https://www.google.com", "WebView 1");
pageAdapter.addWebViewItem("https://m.bbc.co.uk", "WebView 2");
pageAdapter.addWebViewItem("http://thorbek.net", "WebView 3");
pageAdapter.addItem(new ContainerFragment(), "container");
pager = (ViewPager) findViewById(R.id.container);
pager.setOffscreenPageLimit(pageAdapter.getCount() - 1);
pager.setAdapter(pageAdapter);
pager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
Log.d("PAGER", "onPageSelected");
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
Log.d("PAGER", "onPageScrolled");
}
@Override
public void onPageScrollStateChanged(int arg0) {
Log.d("PAGER", "onPageScrollStateChanged");
final int currentItem = pager.getCurrentItem();
final BarFragment barFragment = (BarFragment) getSupportFragmentManager()
.findFragmentById(R.id.bar);
barFragment.setCurrentItem(currentItem);
}
});
layoutTabBar = (FrameLayout) findViewById(R.id.bar);
initAnimation();
}
private void initAnimation() {
...
}
public static class BarFragment extends Fragment {
private final List<Button> buttons = new ArrayList<Button>();
private int currentIndex = -1;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_buttonbar,
container, false);
initButtons(rootView);
return rootView;
}
@SuppressWarnings("deprecation")
public void setCurrentItem(int index) {
if (currentIndex != index) {
resetButtons();
buttons.get(index).setBackgroundDrawable(
buttons.get(index).getContext().getResources()
.getDrawable(R.drawable.button_settings_pressed));
currentIndex = index;
}
}
@SuppressWarnings("deprecation")
private void initButtons(final View rootView) {
...
}
@SuppressWarnings("deprecation")
private void resetButtons() {
...
}
}
Java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.test.MainActivity$BarFragment: make sure class name exists, is public, and has an empty constructor that is public
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2351)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2403)
at android.app.ActivityThread.access$700(ActivityThread.java:165)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1379)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5391)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.test.MainActivity$BarFragment: make sure class name exists, is public, and has an empty constructor that is public
at android.support.v4.app.Fragment.instantiate(Fragment.java:435)
at android.support.v4.app.FragmentState.instantiate(Fragment.java:101)
at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1823)
at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:264)
at com.example.test.MainActivity.onCreate(MainActivity.java:79)
at android.app.Activity.performCreate(Activity.java:5122)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1150)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2315)
Caused by: java.lang.IllegalAccessException: access to class not allowed
at java.lang.Class.newInstanceImpl(Native Method)
at java.lang.Class.newInstance(Class.java:1319)
at android.support.v4.app.Fragment.instantiate(Fragment.java:420)
MainActivity.java:79 is at super.onCreate(savedInstanceState);
So it is being thrown immediately in onCreate of MainActivity.
Upvotes: 2
Views: 4987
Reputation: 1268
The exception is quite clear.
make sure class name exists, is public, and has an empty constructor that is public
Your BarFragment class has to be public
public static class BarFragment extends Fragment
Alternatively you can avoid fragment re-creation by doing the following when creating the fragment
fragment.setRetainInstance(true)
Upvotes: 3
Reputation: 11
When the orientation changes the activity is recreating again you have to use savedInstanceState maintain the fragmented state.
if(savedInstanceState == null)
{
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
Upvotes: 0
Reputation: 11
setRetainInstance(true);
I have just put this line and it solved my problem.
Example of my code :
public class PlaceholderFragment extends Fragment{
String str;
public PlaceholderFragment (String strDesc1){
this.str=strDesc1;
setRetainInstance(true); //Hear put this line
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.quiz_play_descrption_frg_one_, null,false);
TextView txtdisc=(TextView) rootView.findViewById(R.id.txt_Discription_quizPlayFragment);
txtdisc.setText(str);
return rootView;
}
}
Upvotes: 0
Reputation: 2039
Looks like your BarFragment is not public. Try changing it to
public static class BarFragment extends Fragment
Also, you should not add your own empty constructor to the fragment. The default constructor will be setup automatically and should correctly handle restoring state. If you need to pass arguments to the fragment try using a static newInstance method and assigning a bundle to it.
See these docs for further explanation:
http://developer.android.com/reference/android/app/Fragment.html#Fragment%28%29
Basically remove the constructor you added.
Good Luck
Upvotes: 1