Android Fragment getArguments() returns null

匿名 (未验证) 提交于 2019-12-03 01:54:01

问题:

As the title suggest.
I've downloaded Fragment code from here, http://developer.android.com/shareables/training/FragmentBasics.zip.
It is Fragment example from Android Official Developer site. http://developer.android.com/training/basics/fragments/fragment-ui.html

This is the MainActivity.java's onCreate():

/** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.news_articles);      // Check whether the activity is using the layout version with     // the fragment_container FrameLayout. If so, we must add the first fragment     if (findViewById(R.id.fragment_container) != null) {          // However, if we're being restored from a previous state,         // then we don't need to do anything and should return or else         // we could end up with overlapping fragments.         if (savedInstanceState != null) {             return;         }          // Create an instance of ExampleFragment         HeadlinesFragment fragment = new HeadlinesFragment();          // In case this activity was started with special instructions from an Intent,         // pass the Intent's extras to the fragment as arguments         //fragment.setArguments(getIntent().getExtras());         Bundle args= new Bundle();         args.putString("category", "clothes");         args.putString("item", "shirts");         fragment.setArguments(args);          // Add the fragment to the 'fragment_container' FrameLayout         getSupportFragmentManager().beginTransaction()                 .replace(R.id.fragment_container, fragment).commit();     } } 

And HeadlinesFragment.java's onCreate():

@Override public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);      // We need to use a different list item layout for devices older than Honeycomb     int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?             android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1;      Bundle args = getArguments();     if (args == null) {         Toast.makeText(getActivity(), "arguments is null " , Toast.LENGTH_LONG).show();     } else {         Toast.makeText(getActivity(), "text " + args , Toast.LENGTH_LONG).show();     }              // Create an array adapter for the list view, using the Ipsum headlines array     setListAdapter(new ArrayAdapter(getActivity(), layout, Ipsum.Headlines));  } 

I've read several QA here, like this one Fragment getArguments() returns null, and many other that related to setArguments() and getArguments(), but still I'm stuck.

And I've moved the Bundle and Toast code to onAttach() and to onCreateView() with no avail. What wrong with the my code? I think I'm missing something, but dunno what is it.
Please Help! Thanks.

Edit:
I'll state my intention more clearly. In FragmentBasic that I downloaded, there's MainActivity.java, HeadlinesFragment.java, and ArticlesFragment.java. The 'communication' from MainActivity.java to ArticlesFragment.java is not the problem here. What I want is to send data from MainActivity.java to HeadlinesFragment.java. Their connection's like this:

-------------------------------------- | MainActivity  HeadlinesFragment | |      |                             | |      |>> ArticlesFragment          | -------------------------------------- 

And HeadlinesFragment is running at Runtime.

*These code works, when using Android gadget with = 600px), As proved by @Tesla1984 below. But what I want is same result either on gadget 600px.

回答1:

@tonny

i've download the FragmentBasics.zip. i only change the argument name.here is the code and result pic.

MainActivity

public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.news_articles);      // Check whether the activity is using the layout version with     // the fragment_container FrameLayout. If so, we must add the first fragment     if (findViewById(R.id.fragment_container) != null) {          // However, if we're being restored from a previous state,         // then we don't need to do anything and should return or else         // we could end up with overlapping fragments.         if (savedInstanceState != null) {             return;         }          // Create an instance of ExampleFragment         HeadlinesFragment fragment = new HeadlinesFragment();          // In case this activity was started with special instructions from an Intent,         // pass the Intent's extras to the fragment as arguments //            firstFragment.setArguments(getIntent().getExtras());         //test         Bundle args= new Bundle();         args.putString("category", "clothes");         args.putString("item", "shirts");         fragment.setArguments(args);          // Add the fragment to the 'fragment_container' FrameLayout         getSupportFragmentManager().beginTransaction()                 .replace(R.id.fragment_container, fragment).commit();     } } 

HeadlinesFragment

public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);      // We need to use a different list item layout for devices older than Honeycomb     int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?             android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1;      Bundle args = getArguments();     if (args == null) {         Toast.makeText(getActivity(), "arguments is null " , Toast.LENGTH_LONG).show();     } else {         Toast.makeText(getActivity(), "text " + args , Toast.LENGTH_LONG).show();     }          // Create an array adapter for the list view, using the Ipsum headlines array     setListAdapter(new ArrayAdapter(getActivity(), layout, Ipsum.Headlines)); } 

here is the result



回答2:

I had the same problem, but solved it :)

My problem was that I had the element in the Activity's XML layout. Therefore the onCreate() of the Fragment was called before the calls in Java code, thus not setting the arguments.

I removed the element from my XML layout and it worked!



回答3:

I've solved it. Looks like the only way to send data from MainActivity.java to HeadlinesFragment.java is from callbacks (If anybody else know other ways, please contribute, then we have some other ways beside this one, helping others with this kind of problem).

The main code from is MainActivity.java's function public Bundle getBundle() {}, then set the interface section on HeadlinesFragment.java, and add public Bundle getBundle();, and last, call it from HeadlinesFragment.java's onCreate.

What confuse me is fragment.setArguments(getIntent().getExtras()); on MainActivity.java's onCreate. They put that code there, and I believing it will works cause it's from Android Official Developer Guide and API http://developer.android.com/training/basics/fragments/fragment-ui.html, but it didn't work (now I believe that piece of code won't do anything). So, anyone who read the tutorial or sample from there, take it with a grain of salt!

Codes below, so everyone can understand it.

MainActivity.java:

    /*  * Copyright (C) 2012 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package com.example.android.fragments;  import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTransaction; import android.widget.Toast;  public class MainActivity extends FragmentActivity          implements HeadlinesFragment.OnHeadlineSelectedListener {      /** Called when the activity is first created. */     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.news_articles);          // Check whether the activity is using the layout version with         // the fragment_container FrameLayout. If so, we must add the first fragment         if (findViewById(R.id.fragment_container) != null) {              // However, if we're being restored from a previous state,             // then we don't need to do anything and should return or else             // we could end up with overlapping fragments.             if (savedInstanceState != null) {                 return;             }              Toast.makeText(getApplicationContext(), "activity", Toast.LENGTH_LONG).show();              // Create an instance of ExampleFragment             HeadlinesFragment fragment = new HeadlinesFragment();              // In case this activity was started with special instructions from an Intent,             // pass the Intent's extras to the fragment as arguments             fragment.setArguments(getIntent().getExtras());              // Add the fragment to the 'fragment_container' FrameLayout             getSupportFragmentManager().beginTransaction()                     .replace(R.id.fragment_container, fragment).commit();         }     }      public void onArticleSelected(int position) {         // The user selected the headline of an article from the HeadlinesFragment          // Capture the article fragment from the activity layout         ArticleFragment articleFrag = (ArticleFragment)                 getSupportFragmentManager().findFragmentById(R.id.article_fragment);          if (articleFrag != null) {             // If article frag is available, we're in two-pane layout...              // Call a method in the ArticleFragment to update its content             articleFrag.updateArticleView(position);          } else {             // If the frag is not available, we're in the one-pane layout and must swap frags...              // Create fragment and give it an argument for the selected article             ArticleFragment newFragment = new ArticleFragment();             Bundle args = new Bundle();             args.putInt(ArticleFragment.ARG_POSITION, position);             newFragment.setArguments(args);             FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();              // Replace whatever is in the fragment_container view with this fragment,             // and add the transaction to the back stack so the user can navigate back             transaction.replace(R.id.fragment_container, newFragment);             transaction.addToBackStack(null);              // Commit the transaction             transaction.commit();         }     }      public Bundle getBundle() {         Bundle args = new Bundle();         args.putString("category", "cloths");         args.putString("item", "shirts");         return args;     } } 

HeadlinesFragment.java:

    /*  * Copyright (C) 2012 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package com.example.android.fragments;  import android.app.Activity; import android.os.Build; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast;  public class HeadlinesFragment extends ListFragment {     OnHeadlineSelectedListener mCallback;      // The container Activity must implement this interface so the frag can deliver messages     public interface OnHeadlineSelectedListener {         /** Called by HeadlinesFragment when a list item is selected */         public void onArticleSelected(int position);         public Bundle getBundle();     }      @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);          Bundle bundle = mCallback.getBundle();         Toast.makeText(getActivity(), "headline fragment " + bundle, Toast.LENGTH_LONG).show();          // We need to use a different list item layout for devices older than Honeycomb         int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?                 android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1;          // Create an array adapter for the list view, using the Ipsum headlines array         setListAdapter(new ArrayAdapter(getActivity(), layout, Ipsum.Headlines));      }      @Override     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle                      savedInstanceState) {          return super.onCreateView(inflater, container, savedInstanceState);     }      @Override     public void onStart() {         super.onStart();          // When in two-pane layout, set the listview to highlight the selected list item         // (We do this during onStart because at the point the listview is available.)         if (getFragmentManager().findFragmentById(R.id.article_fragment) != null) {             getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);         }     }      @Override     public void onAttach(Activity activity) {         super.onAttach(activity);          // This makes sure that the container activity has implemented         // the callback interface. If not, it throws an exception.         try {             mCallback = (OnHeadlineSelectedListener) activity;         } catch (ClassCastException e) {             throw new ClassCastException(activity.toString()                     + " must implement OnHeadlineSelectedListener");         }     }      @Override     public void onListItemClick(ListView l, View v, int position, long id) {         // Notify the parent activity of selected item         mCallback.onArticleSelected(position);          // Set the item as checked to be highlighted when in two-pane layout         getListView().setItemChecked(position, true);     } } 


回答4:

It looks like you are inserting a key and value pair into your bundle. You probably need to reference the key value as in getArguments().getString(category);

According to the docs for putString: Inserts a String value into the mapping of this Bundle, replacing any existing value for the given key. Either key or value may be null.

Parameters key a String, or null value a String, or null



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!