Android Can';无法为片段找到合适的onCreate()等效项

Android Can';无法为片段找到合适的onCreate()等效项,android,android-fragments,Android,Android Fragments,我已经读过: 我正在将一些活动代码移动到一个全新的片段中,但在先前的onCreate()中发现代码有问题 使用片段的目的:选项卡 在每个选项卡开关上调用的代码: FragmentManager fm=getSupportFragmentManager() FragmentTransaction ft=fm.beginTransaction() ft.replace(R.id.tabContent,fragment1) ft.commit() 其中fragment1、fragment2等是活动

我已经读过:

我正在将一些活动代码移动到一个全新的片段中,但在先前的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服务来获取数据以填充列表。根据片段的生命周期,有几个候选代码,但没有一个完全有效:

  • onCreate():在onCreateView()之前调用。因此,视图层次结构尚未初始化,调用webservice是不安全的

  • onCreateView():当我切换tab/运行显示的代码段时,始终会调用此函数

  • onActivityCreated():我以为只有在创建活动后才会调用它,但它总是在Fragment.onCreateView()之后调用

  • 作为附带问题,您是否建议在片段中调用Web服务?我在网上找不到这方面的任何信息,但不知道为什么它是不正确的


    提前谢谢

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

    说到web服务,您可能可以从任何地方调用,但不能从GUI线程调用(Android将不允许)-因此,创建您自己的therad。当对web服务的某些调用挂起时,您可能不需要支持在片段和活动之间完全切换;如果确实需要,请使用
    savedInstanceState
    捆绑包保存并在请求时恢复状态。

    使用加载程序:

    创建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;
    }
    }
    
    公共抽象类MyLoader扩展了AsyncTaskLoader{
    公共MyLoader(上下文){
    超级(上下文);
    }
    私有字符串结果;
    保护字符串错误;
    @凌驾
    公共最终字符串加载背景(){
    试一试{
    错误=null;
    //使用HTTP从服务器加载数据,并将结果作为字符串存储在“result”中。
    ...
    结果=。。。
    ...
    返回结果;
    }
    捕获(例外e){
    Logger.e(“ResourceLoader”,“加载资源失败”,e);
    错误=e.getMessage();
    }
    返回null;
    }
    @凌驾
    开始加载时受保护的void(){
    如果(!TextUtils.isEmpty(错误)){
    交付结果(结果);
    }
    if(takeContentChanged()){
    力载荷();
    }
    }
    @凌驾
    公共void deliverResult(字符串数据){
    if(isReset()){
    返回;
    }
    结果=数据;
    如果(isStarted()){
    试一试{
    super.deliverResult(数据);
    }
    捕获(例外e){
    Log.e(“ResourceLoader”,“在传递结果时捕获异常。”,e);
    }
    }
    }
    公共字符串getError(){
    返回误差;
    }
    }
    
    在片段中,可以初始化此加载程序:

    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);
            ....
        }
        ...
    }
    ....
    }
    
    公共类Fragment1扩展了片段实现LoaderCallbacks{
    ....
    ....
    字符串消息;
    文本视图文本视图;
    @凌驾
    创建时的公共void(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setRetainInstance(真);
    ....
    }
    @凌驾
    CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态){
    视图=。。。。
    ...
    textView=(textView)view.findViewById(R.id…);
    textView.setMessage(message);//如果此碎片1在方向更改后幸存下来。
    }
    @凌驾
    已创建ActivityState上的公共无效(Bundle savedInstanceState){
    super.onActivityCreated(savedInstanceState);
    getLoaderManager().initLoader(0,getArguments(),this);//在创建活动后开始加载数据。
    }
    @凌驾
    公共加载器onCreateLoader(int-id,Bundle-args){
    返回新的MyLoader(getActivity());//使用MyLoader加载数据
    }
    @凌驾
    public void onLoadFinished(加载器,字符串结果){
    //这里是“result”中的结果。
    消息=结果;
    if(textView!=null){
    //根据结果更新用户界面。
    textView.setText(消息);
    ....
    }
    ...
    }
    ....
    }
    

    在onLoadFinished中,您将结果存储在“message”中。如果结果是一个简单的字符串不够,您可以更改MyLoader和LoaderCallbacks以返回和处理更复杂的数据结构(例如,List).

    没有什么是不正确的,但既然您是在活动中使用此代码开始的,为什么不将调用留在活动和片段中,检查数据,如果数据不在,请活动将其获取好,一方面,因为我认为webservice调用只是片段的事务,那么为什么不呢