Issue
As the question indicates, I am trying to call a Fragment's method from it's parent Activity's onCreate. However, the called method yields a null pointer exception at the Fragment. The offending line is:
getListView().setAdapter(aAdapter);
My suspicion is the getListView() does not yet exist. Perhaps it is a gap in my knowledge of Fragment/Activity lifecycles, but is there an "AfterCreate" in an Activity that I could use?
//Views
private RelativeLayout vClassSettings;
private LinearLayout vPeople;
private LinearLayout vLinks;
private RelativeLayout vAttendanceSettings;
private static final String sTag = "ActivityClassEdit";
private Boolean insertMode;
//==============On Create================
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_classedit);
vClassSettings=(RelativeLayout) findViewById(R.id.ace_container_settings);
vPeople = (LinearLayout) findViewById(R.id.ace_container_people);
vLinks = (LinearLayout) findViewById(R.id.ace_container_links);
vAttendanceSettings = (RelativeLayout) findViewById(R.id.ace_container_attendanceDetails);
insertMode=true;
startupFragments();
}
/*
Sets modes for children fragments so that we do not get null adapters, be it Object or SQL related
*/
private void startupFragments(){
instantiateFragments();
if(insertMode){
if(fLinkList==null){Log.d(sTag,"null fragment for LinkList");}
fLinkList.setArrayMode();
fCrList.setArrayMode();
fPersonList.setArrayMode();
} else {
//TODO set CursorMode with parent class argument
}
}
And the fragment's offending method:
public void setArrayMode(){
aAdapter = new LinkArrayListAdapter(getActivity(), links);
getListView().setAdapter(aAdapter);
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
final LinkTable.Link selectedLink = (Link) parent.getItemAtPosition(position);
selectedLink.setIndex(aAdapter.getPosition(selectedLink));
App.getInstance().getEventBus().post(new FragmentEvent.LinkObjectLoad(selectedLink));
//App.getInstance().getEventBus().post(arg0);
}});}
Solution
I would suggest that you never touch the Fragment's View from outside of the Fragment itself. The Fragment should create it's View in onCreateView()
, grab view references and initialize the View in onViewCreated()
, and release it in onDestroyView()
. If you need to provide data to it after it's created, you could either:
Provide a method in your Fragment to set the data for the adapter. If the View has not yet been created, the data should be picked up when the Fragment sets the adapter. Otherwise, the fragment can update its adapter with the new data.
Provide the data as Fragment arguments (
Fragment.setArguments(Bundle)
) and have the Fragment set the list adapter inonViewCreated()
withgetArguments().get{someDataType}()
.
EDIT: So provide arguments to the Fragment:
public static MyListFragment newInstance(int type, ArrayList<? extends Parcelable> items) {
MyListFragment fragment = new MyListFragment();
Bundle args = new Bundle();
args.putInt(TYPE_ARG, type);
args.putParcelableArrayList(ITEMS_ARG, items);
fragment.setArguments(args);
return fragment;
}
public void onViewCreated(View view, Bundle savedInstanceState) {
final int type = getArguments().getInt(TYPE_ARG);
if (type == FIRST_TYPE) {
// Set first type adapter
} else /* Some other type of argument */ {
// Set another adapter type
}
}
Although I'd suggest if the two types are very different, maybe have one base fragment with shared behavior, and have subclasses for each adapter type, and instantiate a different fragment from the Activity depending on whatever arguments you're using to decide.
Answered By - Kevin Coppock
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.