找不到合适的onCreate()等效片段

时间:2013-02-04 18:44:47

标签: android android-fragments

我已经读过这个: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.
  • 我希望它们如何工作:与活动(!)一样,意味着:创建后 - 我调用我的webservice,并且第一次初始化列表时,不再有初始化,因此,当我切换标签时,列表仍然保留了我离开它的方式(滚动等),当我回来时,没有视图初始化或webservice调用,它只是再次出现。与活动中一样,如果我启动其他活动并返回 - onCreate()将不会被调用,只会onResume()。因为我只在onCreate()初始化,所以没关系。

我在onCreate()中调用一个web服务来获取数据以填充列表。根据片段的生命周期,有一些候选者可以放置这些代码,但没有一个完全起作用:

  1. onCreate():在onCreateView()之前调用它。因此,视图层次结构尚未初始化,调用Web服务也不安全。

  2. onCreateView():当我切换制表符/运行显示的代码片段时,总会调用此方法。

  3. onActivityCreated():我认为在创建活动之后这将被称为 ,但在Fragment.onCreateView()始终 >

  4. 作为一个附带问题,您是否建议在片段中调用webservices?在网上没有找到任何相关信息,但不知道为什么不正确。

    提前致谢!

2 个答案:

答案 0 :(得分:1)

对我来说,onActivityCreated或多或少似乎是匹配阶段(此时已经可以在父活动上调用findViewById并在片段实例/集中设置组件/ assign字段(不要添加)听众。我的onActivityCreated是这样的,不止一次运行它不会造成任何伤害,并且会考虑传递的Bundle参数。

谈到Web服务,你可能可以从任何地方打电话,但你不能从GUI线程调用(Android不允许) - 所以创建自己的therad。您可能不需要支持在片段和活动之间完全切换,而某些对Web服务的调用正在等待处理;如果确实需要,请使用savedInstanceState包来保存并在请求时恢复状态。

答案 1 :(得分:1)

使用装载程序:

创建AsyncLoader的子类,并在Fragment的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中,将结果存储在“message”中。如果一个简单的String不足以作为结果,您可以更改MyLoader和LoaderCallbacks以返回并处理更复杂的数据结构(例如,List&lt; String&gt;)。