我有BlankFragment
package com.hfad.addingafragmenttoframelayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.w3c.dom.Text;
/**
* A simple {@link Fragment} subclass.
*/
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message","onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
public void setText(String textToBeSet){
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
tv.setText(textToBeSet);
}
}
它的布局是:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.hfad.addingafragmenttoframelayout.BlankFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment"
android:id="@+id/fragmentText"/>
</FrameLayout>
以下是MainActivity
package com.hfad.addingafragmenttoframelayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//BlankFragment bf = new BlankFragment();
//getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, bf).commit();
BlankFragment bf = new BlankFragment();
bf.setText("hello world");
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, bf).commit();
}
}
这是MainActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.hfad.addingafragmenttoframelayout.MainActivity"
android:orientation="vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fragment_container"
/>
</LinearLayout>
在onCreate活动方法中,我将片段添加到布局中。这工作正常,除非我尝试使用setText方法更改文本。
我收到了这个错误:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at com.hfad.addingafragmenttoframelayout.BlankFragment.setText(BlankFragment.java:35)
at com.hfad.addingafragmenttoframelayout.MainActivity.onStart(MainActivity.java:29)
参考这一行
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
有人可以解释造成这种异常的原因吗?
答案 0 :(得分:17)
<强>唐&#39;吨强>
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message","onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
public void setText(String textToBeSet){
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
tv.setText(textToBeSet);
}
<强>不要强>
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View RootView = inflater.inflate(R.layout.fragment_blank, container, false);
TextView tv = (TextView)RootView.findViewById(R.id.fragmentText);
tv.setText("HI");
return RootView;
}
答案 1 :(得分:1)
下面:
bf.setText("hello world");
行导致问题,因为在setText
中添加Fragment
之前调用了片段FragmentManager
方法。
添加setText
片段后调用bf
方法:
getSupportFragmentManager().beginTransaction().
add(R.id.fragment_container, bf).commit();
bf.setText("hello world"); // call here
答案 2 :(得分:0)
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
在onCreateView();
中执行答案 3 :(得分:0)
在尚未创建视图时,您可以使用可容纳String
的临时变量。
private TextView tv;
private String holder = "";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_blank, container,false);
tv = (TextView)v.findViewById(R.id.fragmentText);
return v;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
tv.setText(holder);
}
public void setText(String textToBeSet){
if(tv != null){
tv.setText(textToBeSet);
}else{
holder = textToBeSet;
}
}
答案 4 :(得分:0)
我的假设是,您希望使用一些初始文本实例化BlankFragment
,并允许稍后从MainActivity
设置文本。
在这种情况下,我会首先更改片段以接受如下的初始文本:
public class BlankFragment extends Fragment {
private static final String ARG_INITIAL_TEXT = "arg_initial_text";
public static BlankFragment newInstance(CharSequence initialText) {
final BlankFragment fragment = new BlankFragment();
final Bundle args = new Bundle();
args.putCharSequence(ARG_INITIAL_TEXT, initialText);
fragment.setArguments(args);
return fragment;
}
public BlankFragment() {
// Required empty public constructor
}
private CharSequence mInitialText;
private TextView mText;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInitialText = getArguments().getCharSequence(ARG_INITIAL_TEXT);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message", "onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mText = view.findViewById(R.id.fragmentText);
mText.setText(mInitialText);
}
public void setText(CharSequence textToBeSet) {
mText.setText(textToBeSet);
}
}
活动代码如下所示:
public class MainActivity extends AppCompatActivity {
private BlankFragment mBlankFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
final Fragment bf = BlankFragment.newInstance("hello world");
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, bf, BlankFragment.class.getName())
.commit();
}
mBlankFragment = (BlankFragment) getSupportFragmentManager()
.findFragmentByTag(BlankFragment.class.getName());
}
private void someTimeLaterWhenWantingToSetNewTextToFragmentFromActivity(CharSequence newText) {
if (mBlankFragment != null) {
mBlankFragment.setText(newText);
}
}
}
请注意,savedInstanceState
的空值检查是为了保护Activity-recreation,例如由于配置更改。
答案 5 :(得分:0)
问题是默认情况下FragmentTransaction是异步的
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, BlankFragment.newInstance);
ft.disallowBackStack();
ft.commitNowAllowingStateLoss();
然后你仍然无法获得片段,你必须从FragmentTransaction中获取它
BlankFragment bf = (BlankFragment) getSupportFragmentManager().getFragmentById(R.id.fragment_container);
bf.setText("hello world");
这article让我更好地理解了这个问题