activity_fragment.xml的代码:
<?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的代码
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的代码
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。为什么Fragment fragment = fm.findFragmentById(R.id.fragmentContainer)为空?请帮帮我。
答案 0 :(得分:11)
首先,您不需要检查片段是否为空,因为当一个活动销毁所有片段时也会被销毁。因此在活动onCreate中将没有片段,您需要在每次重新创建活动时添加它。
其次不要使用findFragmentById。在xml文件中定义片段时,只能使用此方法。既然您动态添加了片段,则需要指定字符串标记,然后使用该标记来查找片段。
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();
}
如果您需要找到您的片段,只需使用此代码
Fragment fragment = fm.findFragmentByTag("TagName");
2019年1月9日更新
自2018年起,您只需使用Google导航库在应用中的页面(片段)之间导航即可。它将处理所有事务,并使导航更容易和更清洁。看看这里
https://developer.android.com/topic/libraries/architecture/navigation/
答案 1 :(得分:1)
当没有带有该ID的片段时,它将为null。这是正常的流程。然而,更好的方法是使用findFragmentByTag。由于您在创建片段时将标记设置为任何内容并在管理器上添加/替换它们,因此很容易通过标记找到并跟踪它们。
答案 2 :(得分:0)
没关系,它是空的。它告诉你片段还没有创建。这就是为什么之后你会创建它的几行。
重新启动/重新创建活动时可以调用onCreate
方法,在这种情况下,用于存在的片段仍然存在,然后引用将不为空。
答案 3 :(得分:0)
我按照建议这样做了,我仍然得到一个空的返回值。
FragmentManager fragMan = getSupportFragmentManager();
FragmentTransaction fragTran = fragMan.beginTransaction();
ControlsFragment ctrlFrag = new ControlsFragment();
fragTran.add(R.id.fragment_container, ctrlFrag, "ctrl");
fragTran.commit(); // commit additions
FragmentManager fm = this.getSupportFragmentManager();
Fragment test = fm.findFragmentByTag("ctrl");
System.out.println(test);
Spinner spin1 = (Spinner)test.getView().findViewById(R.id.rythmspinner2);
System.out.println(spin1);
if (spin1 != null) spin1.setSelection(3);
答案 4 :(得分:0)
我在我调用public class PlayerAdapter extends RecyclerView.Adapter<PlayerAdapter.PlayerHolder>{
private List<Players> playerList;
public PlayerAdapter(List<Players> list) {
playerList = list;
}
/* ViewHolder for each item */
public class PlayerHolder extends RecyclerView.ViewHolder {
EditText playerName;
PlayerHolder(View itemView) {
super(itemView);
Log.e("Holder","setview");
playerName = itemView.findViewById(R.id.name);
MyTextWatcher textWatcher = new MyTextWatcher(playerName);
playerName.addTextChangedListener(textWatcher);
}
}
@Override
public PlayerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.new_player_item_layout, parent, false);
return new PlayerHolder(itemView);
}
@Override
public void onBindViewHolder(PlayerHolder holder, int position) {
Players playerItem = playerList.get(position);
//Sets Text
//holder.playerName.setText(playerItem.getName());
holder.playerName.setTag(R.string.listSize, playerList.size());
holder.playerName.setTag(R.string.position, position);
}
@Override
public int getItemCount() {
return playerList.size();
}
public void updateList(List<Players> newList){
playerList = newList;
notifyDataSetChanged();
}
}
的行之前添加了以下代码行并获取空值,以便为我提供存在的片段列表:
findFragmentById
然后,我通过点击左侧的列添加了一个断点。然后,我以调试模式运行应用程序。当我点击该断点并在列表中看到我想要的片段时,我在调试器中查看了List<Fragment> listFrags = getActiveFragments();
。我找了以下两个值:
listFrags
(由mTag
返回)findFragmentByTag
(由mFragmentId
返回)通过检查这种方式,我了解到我需要使用findFragmentById
来获取我想要的片段,而不是findFragmentByTag
。我希望这个解决方案和/或这些调试步骤对你们中的一个或多个人有所帮助。
答案 5 :(得分:0)
在我的情况下,问题是我在添加片段之后调用了“ findFragmentById()”方法,因此事务未完成。
因此,在调用此方法之前,我立即调用了“ excutePedingTransactions()” 问题就解决了。
答案 6 :(得分:0)
Sinory,这个故事比公认的11个答案深得多!
让我开始说:所有Android开发人员必须深刻理解我们不拥有Android组件。这意味着我们不会创建它们,也不会销毁它们。这些都是由Android系统完成的。我们唯一可以做的就是获取回调。这些是我们可以运行代码的挂钩。您可能会以为我不喜欢这个话题了,但是很快您就会明白为什么我从这个段落开始了。
已接受的答案中的问题:“它将始终为null”否,绝对错误。
现在让我们了解您为何编写此代码以及您理解的错误(不仅是您的代码):
您有回调onCreate(),然后您想到了哦!以前我添加了一个片段。也许是第一次,它将为null,下次添加后,我将在FragmentManager中获得该实例! 您之所以这么想,是因为您错过了了解谁杀死了他们的活动!
您知道吗,如果Android破坏了您的活动,那么在休闲时您会发现您的Fragment!实际上,在尝试重新添加时,您将使代码崩溃。但是请记住,这些都是新实例,它们只是模仿先前的被杀死对象,以使UI上的用户不会感到困惑。这是怎么发生的?读取Activity和片段的onSaveInstanceState和onRestoreInstanceState作为Activity的信息,并读取onViewStateRestored作为片段的方法。
所以我真的回到了被杀害的INSTACE!
让我们看看如何杀死该活动
按用户:通过按“后退”按钮,活动从任务的后退堆栈中弹出,因此该对象被破坏。现在用户打算销毁,所以故事到此结束。重新启动活动后,一切都将开始全新!没有在先前实例上执行的任何先前动作的痕迹。这有道理吧?因为您想离开屏幕,所以为什么还要期待为您设置相同的场景!说得通?
通过Android:发生这种情况的原因有很多,请阅读有关它的文档。简而言之,当您单击“主页”按钮并且用户的活动不在表面上,用户无法进行交互时,Android很难找到用户可能正在做的更重要工作的内存。然后它开始杀死背景。并在那里杀死您的活动! ....但是,嘿,现在您又是用户,当您再次返回该被杀死的活动时,这次您希望此活动完全正确!!但是对象被Android杀死了。
Android进行的对象娱乐:所以现在,当Android杀死它时,它负责做一些聪明的事情,并试图在他离开时将其呈现给用户,但是还是要!作为开发人员,Android需要您的帮助,以便在正确的回调钩子等处编写代码以完成任务。所以它的作用是:
,在这种情况下,新的fragmentManager实例仍可以在其中找到该片段,并且您的片段将不为空!!!欢呼
因此,可以通过代码获取非null片段,但是编写此代码的正确方法是确定谁杀死了实例。一种方法是检查savedInstanceBundle是否为null。如果为null,则表示用户杀死了该实例,或者它是有史以来第一个实例!
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.
,因此您找到了片段。但是,嘿,新发现的片段是一个NEW INSTANCE。而不是以前的。记住,每个人都在尝试模仿。
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的理解,并从长期中受益。