1

私はすでにこれを読んでいます:http://developer.android.com/guide/components/fragments.html

一部のアクティビティ コードを新しいフラグメントに移動していますが、以前の onCreate() のコードに問題が見つかりました。

  • フラグメントを使用する目的: タブ。

  • 各タブ スイッチで呼び出されるコード:

    FragmentManager fm = getSupportFragmentManager();

    FragmentTransaction ft = fm.beginTransaction();

    ft.replace(R.id.tabContent, fragment1);

    ft.commit();

fragment1、fragment2 などは、アクティビティのインスタンス変数であり、次のようにインスタンス化されonCreateます。

fragment1 = new Fragment1();
//etc.
  • どのように動作させたいか: アクティビティ (!) と同様に、次のことを意味します: 作成後 - Web サービスを呼び出し、リストが最初に初期化される場所で、初期化がなくなるため、タブを切り替えてもリストはそのまま残ります。私はそれを残しました(スクロールなど)。戻ってくると、ビューの初期化やWebサービスの呼び出しはなく、再び表示されます。アクティビティのように、別のアクティビティを起動して戻ってきた場合、 -onCreate()は呼び出されず、onResume(). でしか初期化していないonCreate()ので大丈夫です。

リストに入力するデータを取得するために、onCreate() Web サービスを呼び出しています。フラグメントのライフサイクルによると、このコードを配置する候補はいくつかありますが、完全に機能するものはありません。

  1. onCreate(): これは onCreateView() の前に呼び出されます。そのため、ビュー階層はまだ初期化されておらず、Web サービスを呼び出すのは安全ではありません。

  2. onCreateView(): これは、タブを切り替えたり、表示されているコード スニペットを実行したりすると常に呼び出されます。

  3. onActivityCreated(): これはアクティビティが作成された後にのみ呼び出されると思っていましたが、常にFragment.onCreateView() の後に呼び出されます

余談ですが、フラグメントで Web サービスを呼び出すことをお勧めしますか? これについてウェブで何も見つけていませんが、なぜ間違っているのかわかりません。

前もって感謝します!

4

2 に答える 2

1

ローダーを使用する:

AsyncLoader のサブクラスを作成し、フラグメントの onActivityCreated 実装でこれらのローダーを開始/初期化します。

public abstract class MyLoader extends AsyncTaskLoader<String> {
public MyLoader(Context context) {
    super(context);
}

private String result;
protected String error;

@Override
public final String loadInBackground() {
    try {
        error = null;
        // Load your data from the server using HTTP and store result as string in 'result'.
        ...
        result = ...
        ...
        return result;
    }
    catch (Exception e) {
        Logger.e("ResourceLoader", "Loading resource failed.", e);
        error = e.getMessage();
    }
    return null;
}

@Override
protected void onStartLoading() {
    if (!TextUtils.isEmpty(error)) {
        deliverResult(result);
    }

    if (takeContentChanged()) {
        forceLoad();
    }
}

@Override
public void deliverResult(String data) {
    if (isReset()) {
        return;
    }

    result = data;

    if (isStarted()) {
        try {
            super.deliverResult(data);
        }
        catch(Exception e) { 
            Log.e("ResourceLoader", "Caught exception while delivering result.", e);
        }
    }
}

public String getError() {
    return error;
}
}

Fragment で、このローダーを初期化できます。

public class Fragment1 extends Fragment implements LoaderCallbacks<String> {
....
....
String message;
TextView textView;

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

    setRetainInstance(true);
        ....
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = ....
    ...
    textView = (TextView)view.findViewById(R.id.....);
    textView.setMessage(message); // in case this Fragment1 survived an orientation change.
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    getLoaderManager().initLoader(0, getArguments(), this); // Start loading data after activity has been created.
}

@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
    return new MyLoader(getActivity()); // Load data using MyLoader
}

@Override
public void onLoadFinished(Loader<String> loader, String result) {
    // Here you have the result in 'result'.
    message = result;
    if (textView != null) {
        // Update UI according to result.
        textView.setText(message);
        ....
    }
    ...
}
....
}

onLoadFinished では、結果を「メッセージ」に格納します。結果として単純な文字列では不十分な場合は、MyLoader と LoaderCallbacks を変更して、より複雑なデータ構造を返して処理することができます (たとえば、List<String> など)。

于 2013-02-04T20:07:32.480 に答える
1

私にとっては、onActivityCreated多かれ少なかれ一致する段階のようです(現時点ではfindViewById、親アクティビティを呼び出してコンポーネントをセットアップする/フラグメントインスタンスにフィールドを割り当てる/リスナーを設定する(追加しない)ことがすでに可能onActivityCreatedです。 once は害を及ぼさず、渡されたBundleパラメーターが考慮されます。

Web サービスについて言えば、おそらくどこからでも呼び出すことができますが、GUI スレッドから呼び出すことはできません (Android では許可されません)。そのため、独自の therad を作成します。Web サービスへの呼び出しが保留中の場合、フラグメントとアクティビティ間の完全な切り替えをサポートする必要はおそらくありません。必要に応じて、savedInstanceStateバンドルを使用して状態を保存し、要求されたときに再開します。

于 2013-02-04T18:55:44.553 に答える