简体   繁体   中英

null object reference of TextView in Fragment

I have two fragments and a main activity. The first fragment, FriendsFragment (extends ListFragment) is displayed on the screen and when the user clicks an item, the main Activity replaces the FriendsFragment with FeedFragment, then calls a method from FeedFragment to update the textView.

I'm getting an error that the textView object in the FeedFragment class is null even though I instantiate using the findViewById method.

I have looked at related questions and have tried the solutions but nothing is working. I've tried doing getView().findViewById(R.id.feed_view) , getActivity().findViewById(R.id.feed_view) , and I've tried putting these in onActivityCreated() and onCreateView()

The only thing that worked is writing this code in onActivityCreated():

text = getView().findViewById(R.id.feed_view); 
text.setText("some string"); 

but this is not what I want

FeedFragments.java

public class FeedFragment extends Fragment {
    private static String TAG = "Feed Fragment";
    private TextView text;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        Log.i(TAG, "Entered FeedFragment.java onActivityCreated()");
        super.onActivityCreated(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    Log.i(TAG, "Entered FeedFragment.java onCreateView()");
    View v = inflater.inflate(R.layout.fragment_feed, container,false);;
    text = v.findViewById(R.id.feed_view);
    return v;
}

public void updateDisplay(int position)
{
    Log.i(TAG, "FeedFragment.java: updateDisplay()");
    text.setText(position);
}

MainActivity.java

// previously declared feedFragment: feedFragment = new FeedFragment(); 
public void onItemSelected(int position)
{
    Log.i(TAG, "Entered onItemSelected(" + position + ")");
    fragManager = getFragmentManager();
    FragmentTransaction fragTransaction = fragManager.beginTransaction();
    fragTransaction.replace(R.id.fragment_container, feedFragment, "feed_fragment");
    fragTransaction.addToBackStack(null);
    fragTransaction.commit();

    feedFragment.updateDisplay(position);
}

fragment_feed.xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

    <TextView
        android:id="@+id/feed_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/greeting" />

</ScrollView>

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />

onViewcreated() is being called after updateDisplay() because the system doesn't run it right away.

you need to pass a value to the feedFragment on it's creation and store it in a bundle and retrieve it after the fragment internal code is run by the system.

the way you solve it is like this:

when you instantiate feedFragment you do it like this:

feedFragment = FeedFragment.newInstance(position)

and inside FeedFragment class you should have a static code:

private static final String ARG_PARAM1 = "param1";

public static FeedFragment newInstance(int param1) {
    FeedFragment fragment = new FeedFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_PARAM1, param1);
    fragment.setArguments(args);
    return fragment;
}

and non static code:

private int mParam1;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getInt(ARG_PARAM1);
    }
} 

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    Log.i(TAG, "Entered FeedFragment.java onCreateView()");
    View v = inflater.inflate(R.layout.fragment_feed, container,false);;
    text = v.findViewById(R.id.feed_view);
    text.setText(String.valueOf(mParam1));
    return v;
}

I wrapped mParam1 in String.valueOf() because when you pass integer to setText it thinks you try to use a Strings.xml resource instead of the number you chose.

also I used very generic variable names. please change them to something meaningful so that your code makes sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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