简体   繁体   English

什么时候以编程方式添加片段的视图?

[英]When does a programmatically added fragment's view get created?

I have a FragmentActivity that I add a single ListFragment to using FragmentTrasaction . 我有一个FragmentActivity ,我使用FragmentTrasaction添加一个ListFragment All fine and well, but I have run into the "Content view not created" errors when trying to set the onItemClickListener of the ListView in the ListFragment , like this: 一切都很好,但是当我尝试在onItemClickListener中设置ListViewListFragment ,我遇到了“内容视图未创建”错误,如下所示:

public class ContactList extends FragmentActivity implements
    LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {

static private final String TAG = ContactList.class.getSimpleName();

private SimpleCursorAdapter mListAdapter;
ListFragment mListFrag;

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

     mListFrag = new ListFragment();


    if (savedInstanceState == null) {
        // add list view fragment
        FragmentTransaction ft = getSupportFragmentManager()
                .beginTransaction();
        ft.add(android.R.id.content, mListFrag);
        ft.commit();
    }

    // set up list view adapter:
    mListAdapter = new SimpleCursorAdapter(this,
            android.R.layout.simple_list_item_1, null,
            new String[] { ContactsContract.Contacts.DISPLAY_NAME },
            new int[] { android.R.id.text1 },
            SimpleCursorAdapter.NO_SELECTION);

    // (we will switch in the cursor later)
    mListFrag.setListAdapter(mListAdapter);

    // set list view click listener:
    // (THIS LINE, I KNOW NOW, CAUSES PROBLEMS - SO I MOVED IT
    //  TO onCreateView):
    //mListFrag.getListView().setOnItemClickListener(this);

    // initial cursor loader:
    getSupportLoaderManager().initLoader(0, null, this);
}

I quickly realised that I was trying to call getListView in the onCreate method, so the ListView was not being shown yet. 我很快意识到我试图在onCreate方法中调用getListView ,因此ListView尚未显示。 So, I moved the line setOnItemClickListener line to onCreateView : 所以,我将setOnItemClickListener行移动到onCreateView

@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    View v = super.onCreateView(name, context, attrs);

    // set list view click listener:
    mListFrag.getListView().setOnItemClickListener(this); // this still crashes

    return v;
}

Unfortunately, this still crashes with a "Content view not yet created" error. 不幸的是,这仍然会因“尚未创建内容视图”错误而崩溃。 I don't understand this - surely after calling super.onCreateView all of the views should have now been created? 我不明白这一点 - 在调用super.onCreateView之后肯定应该创建所有的视图吗?

I finally got the inItemClickListener to work by putting it on 'onResume()', but I don't know why it did't work in onCreateView . 我终于通过将它放在'onResume()' inItemClickListener使inItemClickListener工作,但我不知道为什么它在onCreateView不起作用。

Can anyone enlighten me? 任何人都可以开导我吗?

Thanks. 谢谢。

Fragment s have own lifecycles and as I recall you can not set listeners on default Fragment lifecycle events from within the containing FragmentActivity (or any other Activity ). Fragment有自己的生命周期,我记得你不能在包含FragmentActivity (或任何其他Activity )的默认Fragment生命周期事件中设置监听器。 Therefore, you can not be sure if the list view has been created already if you use the default ListFragment . 因此,如果使用默认的ListFragment ,则无法确定是否已创建列表视图。

I finally got the inItemClickListener to work by putting it on 'onResume()', but I don't know why it did't work in onCreateView. 我终于通过将它放在'onResume()'上来使inItemClickListener工作,但我不知道为什么它在onCreateView中不起作用。

This might work for you, but also isn't safe because it has no knowledge of the Fragment's lifecycle state. 这可能对您有用,但也不安全,因为它不了解Fragment的生命周期状态。

The default/best practice here is the following: write your own Fragment class, let it extend ListFragment and put the onClick logic in the onListItemClick() method of your fragment. 这里的默认/最佳实践如下:编写自己的Fragment类,让它扩展ListFragment并将onClick逻辑放在片段的onListItemClick()方法中。

Background: 背景:
Setting any listeners on UI events of a Fragment should happen inside the Fragment itself, not in the containing Activity. 在Fragment的UI事件上设置任何侦听器应该在Fragment本身内部发生,而不是在包含Activity中。 That's one of the reasons why Fragments have been introduced: to provide mostly independent components (with an own lifecycle) that can be combined and re-used. 这就是为什么引入Fragments的原因之一:提供可以组合和重用的大多数独立组件(具有自己的生命周期)。 Otherwise, you could just use a ListActivity . 否则,您可以使用ListActivity

OnCreateView创建一个视图,使其在返回后可用,但不能在执行之前或执行期间使用。

After ft.commit just call getSupportFragmentManager().executePendingTransactions(); ft.commit之后只需调用getSupportFragmentManager().executePendingTransactions(); ( executePendingTransactions ). executePendingTransactions )。

This forces the system to immediately execute the ft.commit which is only scheduled to be executed by default. 这会强制系统立即执行仅默认执行的ft.commit

After that your ListView should be ready to be accessed to define the OnClickListener (inside your FragmentActivity ) 之后,您的ListView应该可以访问以定义OnClickListener (在FragmentActivity

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM