Je suis coincé ici avec un problème de démarrage d'une activité à partir d'un bouton à l'intérieur d'un fragment. Voici mon code:
ViewPagerAdapter.Java
import Java.util.List;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentPagerAdapter;
public class ViewPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
@Override
public int getCount() {
return this.fragments.size();
}
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
}
ViewPagerActivity.Java
import Java.util.List;
import Java.util.Vector;
import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentActivity;
import Android.support.v4.view.ViewPager;
import Android.util.Log;
import com.package.here.Class1Overview;
import com.package.here.Class1Overview;
import com.package.here.Class1Overview;
public class ViewPagerActivity extends FragmentActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.viewpager);
ViewPager pager = (ViewPager)super.findViewById(R.id.my_viewpager);
pager.setAdapter(initialisePaging());
}
private ViewPagerAdapter initialisePaging() {
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, Class1Overview.class.getName()));
fragments.add(Fragment.instantiate(this, Class2Overview.class.getName()));
fragments.add(Fragment.instantiate(this, Class3Overview.class.getName()));
return new ViewPagerAdapter(super.getSupportFragmentManager(), fragments);
}
}
Class1Overview.Java (Voici le bouton)
import Android.content.Intent;
import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.view.ViewGroup;
import Android.widget.Button;
import Android.widget.LinearLayout;
import com.package.here.R;
public class FuelOverview extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
return null;
}
View v = (LinearLayout)inflater.inflate(R.layout.class_one_layout, container, false);
View AddBtn = v.findViewById(R.id.btn_add);
((Button) AddBtn).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(getActivity(), ActivityToStart.class);
startActivity(intent);
}
});
return v;
}
}
Et voici mon LogCat :
01-05 19:39:00.913: E/AndroidRuntime(10557): Uncaught handler: thread main exiting due to uncaught exception
01-05 19:39:01.034: E/AndroidRuntime(10557): Java.lang.RuntimeException: Unable to pause activity {com.package.here/com.package.here.ViewPagerActivity}: Java.lang.NullPointerException
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.ActivityThread.performPauseActivity(ActivityThread.Java:3162)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.ActivityThread.performPauseActivity(ActivityThread.Java:3119)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.ActivityThread.handlePauseActivity(ActivityThread.Java:3102)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.ActivityThread.access$2400(ActivityThread.Java:119)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1870)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.os.Handler.dispatchMessage(Handler.Java:99)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.os.Looper.loop(Looper.Java:123)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.ActivityThread.main(ActivityThread.Java:4363)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Java.lang.reflect.Method.invokeNative(Native Method)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Java.lang.reflect.Method.invoke(Method.Java:521)
01-05 19:39:01.034: E/AndroidRuntime(10557): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:860)
01-05 19:39:01.034: E/AndroidRuntime(10557): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:618)
01-05 19:39:01.034: E/AndroidRuntime(10557): at dalvik.system.NativeStart.main(Native Method)
01-05 19:39:01.034: E/AndroidRuntime(10557): Caused by: Java.lang.NullPointerException
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.Java:1576)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.Java:1617)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.Java:481)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.Activity.performSaveInstanceState(Activity.Java:1022)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.Java:1180)
01-05 19:39:01.034: E/AndroidRuntime(10557): at Android.app.ActivityThread.performPauseActivity(ActivityThread.Java:3144)
01-05 19:39:01.034: E/AndroidRuntime(10557): ... 12 more
01-05 19:39:01.423: I/dalvikvm(10557): threadid=7: reacting to signal 3
ViewPager lui-même fonctionne bien. Il semble que ce soit une erreur de pause de FragmentActivity, mais je ne peux pas le comprendre. La seule chose que j'ai trouvée était ce post sur google http://code.google.com/p/Android/issues/detail?id=19917
J'ai également parcouru l'exemple de code google pour m'assurer d'utiliser principalement la même technique ...
Edit: pour m'assurer que ClickListener fonctionne, j'ai essayé un Toast dans la méthode onClick - fonctionne parfaitement.
C'est un problème connu et je suis choqué de constater que personne n'a déposé de bug sur le tracker de bug public pour cela.
Votre problème vient de ceci:
if (f.mSavedViewState != null) {
if (result == null) {
result = new Bundle();
}
result.putSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
// Only add this if it's not the default value
result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}
Vous devriez remarquer que si result
est null
entrant dans ce code et que le premier if
n'est pas déclenché, vous obtiendrez un NullPointerException
si nous entrons dans le second if
.
Il devrait se lire:
if (f.mSavedViewState != null) {
if (result == null) {
result = new Bundle();
}
result.putSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
if (result == null) {
result = new Bundle();
}
// Only add this if it's not the default value
result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}
J'ai soumis un patch pour cela il y a une semaine ou deux: https://Android-review.googlesource.com/31261
La solution rapide est
class MyFragment extends Fragment {
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
setUserVisibleHint(true);
}
Et attendez la mise à jour en mode sans échec :)
Selon un article ici , vous devriez utiliser FragmentStatePagerAdapter plutôt que FragmentPagerAdapter. J'ai eu le même problème que vous avez décrit, et faire en sorte que ce changement fonctionne pour moi.
J'ai juste eu le même problème - le problème pour moi a été causé lorsque j'ai ajouté un nouveau fragment à mon projet avec une mise en page vide. Il semble que si rien n'est enregistré dans le bundle pendant Fragment.onSaveInstanceState(Bundle outState)
cela provoque une exception de pointeur nul dans FragmentManagerImpl.saveFragmentBasicState
.
L'ajout de vues à mes mises en page a résolu le problème (après des heures passées à me cogner la tête contre un mur). Utilisation de Android support library v4 revision 10.
De plus, lorsque vous utilisez un ListView
comme racine pour la disposition des fragments, si la liste ne contient aucun élément, vous obtiendrez également le plantage. Dans la classe fragment, remplacez onSaveInstanceState
comme ceci pour mettre des données dans le bundle:
@Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putString("DO NOT CRASH", "OK");
}