4

私と同様の質問を持つトピックを見つけましたが、今のところ探している答えが見つかりません。私のアプリケーションは、各タブにフラグメントを持つ (FragmentPagerAdapter の子)FragmentActivityをホストする で構成されています。ViewPagerAdapter私の ViewPagerAdapter は、親アクティビティの OnCreateView 関数でインスタンス化されます

_adapter = new ViewPagerAdapter(getApplicationContext()
                         , getSupportFragmentManager()
                         , numOfTabs
                         , status);

ViewPagerAdapter は最低限必要なメソッド getItemを実装しgetCountgetItemPosition

MygetItemは、位置ごとに異なる Fragment を初期化します。

    @Override
public Fragment getItem(int position) 
{
    Fragment f = new Fragment();
    Log.d("Adbox",String.format("Inside ViewPagerAdapter.getItem(%s)",position));

    switch(position)
    {
        case 0:
            Log.d("Adbox","All offers  ==");
            f=FragmentAllOffers.newInstance(_context);
            f.setRetainInstance(true);
            break;
        case 1:
            Log.d("Adbox","Nearby offers  ==");
            f=FragmentNearbyOffers.newInstance(_context);
            //f.setRetainInstance(true);
            break;
        case 2:
            Log.d("Adbox","My coupons  ==");
            f=FragmentCoupons.newInstance(_context);
            f.setRetainInstance(true);
            break;
        case 3:
            Log.d("Adbox","Account  ==");
            f=FragmentAccount.newInstance(_context);
            f.setRetainInstance(true);
            //f=LayoutLocal.newInstance(_context);  
            break;
        case 4:
            Log.d("Adbox","Preferences  ==");
            f=FragmentPreferences.newInstance(_context);
            f.setRetainInstance(true);
            break;
        default:
            break;
    }
    return f;
}

への呼び出しsetRetainInstance(true)は、私が直面している問題を解決するために追加されましたが、どちらも助けにはなりませんでした。

最後に、上記の各フラグメントは、アプリケーション コンテキストを引数として public static newInstance() 関数を実装します。たとえば、FragmentNearbyOffers には次のものが含まれます。

    public static android.support.v4.app.Fragment newInstance(Context ctx)
{
    FragmentNearbyOffers f = new FragmentNearbyOffers();
    ctx = context;
    //Bundle bdl = new Bundle();
    return f;
}

もう 1 つの重要な情報は、親アクティビティが singleInstance として宣言されていることです。いくつかの理由により、これをこのように維持したいと考えています。

すべて正常に動作しますが、アクティビティがしばらくの間バックグラウンドにあり、TaskManager を介して、またはアプリケーション アイコンをクリックしてアクティビティに戻ろうとすると、例外が発生します。

android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.advisor.FragmentNearbyOffers$1: make sure class name exists, is public, and has an empty constructor that is public

クラス名は間違いなく存在し、公開されており、空のコンストラクターを持っているようなコンストラクターはありません.空のコンストラクターを明示的に追加しましたが、呼び出されていることを確認しましたが、これも役に立ちませんでした。

ここのさまざまな投稿から私が理解したのは、Android がアプリケーションを再開するときに、元のアクティビティにリンクされていないフラグメントの新しいインスタンスを FragmentPagerAdapter に配置していることです。 nullを受け取ります..しかし、空のコンストラクターがあるため、この例外が発生する理由がわかりません...実行がアクティビティのonCreateに入り、すぐに入るため、これを修正する場所さえわかりませんフラグメントの空のコンストラクターと例外が発生します..フラグメントの他のメソッド、つまりonAttach、onCreateなどはまったく呼び出されません..したがって、フラグメントを構築するときに実際にクラッシュしているようです..

役立つ場合に備えて、取得しているスタックトレース全体を添付しています。

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.advisor/com.advisor.AdBoxWidgetConfigurationFragment}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.advisor.FragmentNearbyOffers$1: make sure class name exists, is public, and has an empty constructor that is public
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
    at android.app.ActivityThread.access$700(ActivityThread.java:140)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4921)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
    at dalvik.system.NativeStart.main(Native Method)
    Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.advisor.FragmentNearbyOffers$1: make sure class name exists, is public, and has an empty constructor that is public
    at android.support.v4.app.Fragment.instantiate(Fragment.java:399)
    at android.support.v4.app.FragmentState.instantiate(Fragment.java:97)
    at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1760)
    at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:200)
    at com.advisor.AdBoxWidgetConfigurationFragment.onCreate(AdBoxWidgetConfigurationFragment.java:60)
    at android.app.Activity.performCreate(Activity.java:5206)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
    ... 11 more
 Caused by: java.lang.InstantiationException: can't instantiate class com.advisor.FragmentNearbyOffers$1; no empty constructor
    at java.lang.Class.newInstanceImpl(Native Method)
    at java.lang.Class.newInstance(Class.java:1319)
    at android.support.v4.app.Fragment.instantiate(Fragment.java:388)
4

2 に答える 2

7

$1エラーの末尾に注意してください。これは、名前付きのフラグメントではなく、匿名クラスへの参照FragmentNearbyOffersです。

フラグメント com.advisor.FragmentNearbyOffers$1 をインスタンス化できません

フラグメントにはデフォルトのコンストラクターが必要であり、匿名クラスはコンストラクターを提供できないため、フラグメントは常に名前付きクラスでなければなりません。Java 言語仕様のセクション 15.9.5.1 には、次のように記載されています。

匿名クラスは、明示的に宣言されたコンストラクターを持つことはできません。

このセクションでは、匿名クラスが宣言されているコンテキストに従って、コンストラクターが自動的に生成されることについても説明します。これらのコンストラクターはすべてパラメーターを持っているため、既定のコンストラクターとは異なるシグネチャを持っています。組み合わされた効果は、匿名クラスがデフォルトのコンストラクターのシグネチャと一致するコンストラクターを持つことができないということです。

独自のファイルでフラグメント クラスを宣言するか、静的なネストされたクラスとして宣言することができます。

  public static class NestedFragment extends BaseFragment { ...

これらの方法はどちらも問題なく機能するはずです。

于 2013-05-31T21:14:43.433 に答える
2

私は問題を解決することができました..例外メッセージが誤解を招くものだったので、それはかなりトリッキーなものでした. フラグメント内には、内部クラスを使用して実行時に作成した別のネストされたフラグメントがありました。

        mMapFragment = new SupportMapFragment()
    {
        @Override
        public void onResume()
        {
            // TODO Auto-generated method stub
            super.onResume();
            //initMap();
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState)
        {
            super.onActivityCreated(savedInstanceState);

            map = mMapFragment.getMap();
            if (map != null)
            {
                // map.setMapType(GoogleMap.MAP_TYPE_NONE);
                map.setMyLocationEnabled(true);
                CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(lat, lng));
                zoom = CameraUpdateFactory.zoomTo(18);
                map.moveCamera(center);
                map.animateCamera(zoom);
            }

        }
    };

アプリケーションがAndroidによって強制終了された後、再開すると、Androidはフラグメントを再作成し、内部クラスのコンストラクターが表示されなかったため、ネストされたフラグメントを再作成できなかったと推測しています。他の投稿で提案されているように、クラスを別のファイルに移動しましたが、うまくいきました。

于 2013-05-11T18:23:34.280 に答える