首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FragmentManager findFragmentById返回null

FragmentManager findFragmentById返回null
EN

Stack Overflow用户
提问于 2014-04-29 15:57:28
回答 7查看 15.1K关注 0票数 5

Activity_fragment.xml的代码:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8" ?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
/>

CrimeListActivity.java代码

代码语言:javascript
复制
package com.sinory.criminalintent;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;

public class CrimeListActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new CrimeListFragment();
    }

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

        Log.d("CrimeListActivity", "create");
    }

}

SingleFragmentActivity.java代码

代码语言:javascript
复制
package com.sinory.criminalintent;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;

public abstract class SingleFragmentActivity extends FragmentActivity {

    protected abstract Fragment createFragment();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);

        if (null == fragment) {
            fragment = new CrimeListFragment();
            fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit();
        }
    }
}

刚开始学习Android。为什么片段片段= fm.findFragmentById(R.id.fragmentContainer)是空的?请帮帮我。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2014-04-29 16:22:29

首先,不需要检查片段是否为null,因为当活动破坏时,所有片段也将被销毁。因此,在活动onCreate中将没有片段,每次活动重新创建时都需要添加它。

第二,不要使用findFragmentById。只有在定义xml文件中的片段时才使用此方法。现在已经动态添加了片段,您需要指定一个string标记,然后使用该标记查找片段。

代码语言:javascript
复制
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_fragment);

    FragmentManager fm = getSupportFragmentManager();
    fm.beginTransaction().add(R.id.fragmentContainer, fragment,"TagName").commit();
}

如果您需要找到您的片段,只需使用以下代码

代码语言:javascript
复制
Fragment fragment = fm.findFragmentByTag("TagName");

更新:2019年1月9日

到2018年,您可以使用在应用程序中的页面(片段)之间导航。它将处理所有事务,使导航变得更容易和更干净。看看这里,https://developer.android.com/topic/libraries/architecture/navigation/

票数 15
EN

Stack Overflow用户

发布于 2019-11-28 00:04:05

辛诺里,这个故事比被接受的和11个被推翻的答案要深得多!

让我首先说:所有Android开发人员都必须深刻地理解,我们并不拥有Android组件。这意味着我们既不创造他们,也不摧毁他们。这一切都是由Android系统完成的。我们唯一能做的就是我们得到的回调。这些是我们可以运行代码的钩子。你可能会认为我被抛出了话题,但很快你就会明白我为什么要从这段话开始。

问题在接受的答案:“它将永远为零”不,绝对错误。

现在让我们了解一下为什么要编写这段代码,以及在理解过程中(而不仅仅是在代码中)出了什么问题:

你得到了回调onCreate(),你想哦!之前我添加了一个片段。也许第一次它将是空的,下一次添加之后,我将在FragmentManager中获得实例!你这么想的原因是因为你错过了了解是谁杀了这个活动!

你知道,如果安卓摧毁了你的活动,你就会在娱乐活动中找到你的碎片!事实上,在尝试重新添加时,您的代码就会崩溃。但是请记住,这些都是新的实例,只是模仿以前被杀死的对象,这样UI上的用户就不会感到迷惑。这是怎么回事?读取活动和片段onSaveInstanceState和onRestoreInstanceState表示活动,onViewStateRestored读取片段方法。

所以我真的要回去找那个杀死了国家统计研究所的人!

让我们看看活动是如何被消灭的

  1. User:按下back按钮,活动从任务的后面堆栈中弹出,因此对象被破坏。现在用户打算破坏这个故事就在这里结束。在重新开始的活动,一切都将开始全新的!没有对前一个实例执行任何先前操作的任何跟踪。这是有道理的,对吧?因为你想离开屏幕,所以你为什么要期待同样的场景再次为你设置!合乎道理?
  2. 通过Android:这种情况发生的原因有很多,请阅读相关文档。简而言之,当你点击home按钮,你的活动不在表面上让用户进行交互时,Android很难为用户现在可能正在做的更重要的工作找到内存。然后它就开始杀死后台的人。然后你的活动就被扼杀了!.但是,现在你作为一个用户,当你再次回到那个被杀死的活动时,这一次你会期望这个活动就是你正确的方式!但是这个物体是被机器人杀死的。

Android的对象娱乐:所以现在,当Android杀死它时,它有足够的责任去做一些聪明的事情,并试图在用户离开它的时候把它呈现给用户,但是又一次!Android需要您的帮助,开发人员可以在正确的回调钩子等处编写代码来完成任务。所以它所做的是:

  1. 在杀死实例之前,它会将该活动实例的状态保存在一个包中,这样开发者也有机会保存他们的数据(如果他们需要的话)。通过回调onSaveInstanceState。
  2. 创建了新的活动实例。
  3. 因此,也创建了新的片段管理器。现在,这两个实例都提供了以前的状态,因此它们可以复制相同的内容,以便完全模仿,就像什么都没有发生一样。

,这是您新的fragmentManager实例仍然可以在本例中找到片段的地方,您的片段将不为空!Hurray

因此,可以用代码获得一个非空片段,但是编写这段代码的正确方法是识别是谁杀死了实例。一种方法是检查savedInstanceBundle是否为空。如果为null,意味着用户杀死了实例,或者它永远是第一个实例!

代码语言:javascript
复制
if (savedInstanceState != null) {
        // Activity was killed by system.
        // Activity state was saved before killing the previous instance,
        // Doing so it also saved all the fragments in the fragmentManager!.
        // NOTE: It won't save the transaction history! so don't expect that 
        // any fragment that was added, and then later in the flow removed will
        // be saved and later found. ok. keep that in mind very important.


        // So when new Activity is created, new FragmentManager is also created, and it also restores its state with the previous snapshot. i.e bundle. by creating a new instance of fragment and adding to itself.

所以你找到了你的碎片。但是新发现的碎片是一个新的实例。而不是以前的那些。记住,每个人都在模仿。

代码语言:javascript
复制
        testFragment = (TestFragment) fm.findFragmentById(R.id.fragment_container);
    } else {
        // User killed, or its the first time ever this activity is created. So           simply create one instance of fragment and add.
        testFragment = new TestFragment();
        fm.beginTransaction().add(R.id.fragment_container, testFragment).commitNow();
    }

我相信如果你阅读、理解和推理的话。这将有助于建立您对Android的理解,并从长远来看是有益的。

票数 2
EN

Stack Overflow用户

发布于 2014-04-29 16:06:04

当没有该id的片段时,它将为null。这是正常的流动。然而,更好的方法是使用findFragmentByTag。由于在创建片段并在管理器上添加/替换它们时,将标记设置为任何标记,因此很容易通过标记找到和跟踪它们。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23369621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档