So I have a FragmentActivity thats working perfectly as it stands.
public class ChallongeEvent extends FragmentActivity {
private TextView tab_text;
private String EVENT_ID, URL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.challonge_act_event);
init();
}
private void init() {
tab_text = (TextView) findViewById(R.id.tab_text);
Intent intent = getIntent();
EVENT_ID = intent.getStringExtra("event_id");
URL = "https://api.challonge.com/v1/tournaments/" + EVENT_ID + ".json";
String titles[] = new String[] { getString(R.string.details), getString(R.string.players) };
int numTabs = titles.length;
EventAdapter adapter = new EventAdapter(getSupportFragmentManager(), titles, numTabs);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
pager.setCurrentItem(numTabs - 1);
SlidingTabLayout sliding_tabs = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
sliding_tabs.setDistributeEvenly(true);
sliding_tabs.setViewPager(pager);
}
#Override
public void onResume() {
super.onResume();
populate();
}
private void populate() {
AsyncGet fetch = new AsyncGet(new AsyncResponse() {
#Override
public void processFinish(String output) {
for (Fragment fragment : getSupportFragmentManager().getFragments())
{
if (fragment instanceof ChallongePlayers) {
((ChallongePlayers) fragment).parsePlayers(output);
} else if (fragment instanceof ChallongeMatches) {
((ChallongeMatches) fragment).parseMatches(output);
}
}
}
});
HttpUrl.Builder urlBuilder = HttpUrl.parse(URL).newBuilder();
urlBuilder.addQueryParameter("api_key", Challonge.API_KEY);
urlBuilder.addQueryParameter("include_participants", "1");
urlBuilder.addQueryParameter("include_matches", "1");
fetch.execute(urlBuilder.build().toString());
}
}
When the FragmentActivity launches, it fetches JSON from an API, then sends the data of this API to several Fragments within the pager. It does this with the following code:
AsyncGet fetch = new AsyncGet(new AsyncResponse() {
#Override
public void processFinish(String output) {
for (Fragment fragment : getSupportFragmentManager().getFragments())
{
if (fragment instanceof ChallongePlayers) {
((ChallongePlayers) fragment).parsePlayers(output);
} else if (fragment instanceof ChallongeMatches) {
((ChallongeMatches) fragment).parseMatches(output);
}
}
}
});
HttpUrl.Builder urlBuilder = HttpUrl.parse(URL).newBuilder();
urlBuilder.addQueryParameter("api_key", Challonge.API_KEY);
urlBuilder.addQueryParameter("include_participants", "1");
urlBuilder.addQueryParameter("include_matches", "1");
fetch.execute(urlBuilder.build().toString());
However, each of these Fragments has a SwipeRefreshLayout within it, that I would like to activate .setRefreshing(true) on before the AsyncTask request. So I made the SwipeRefreshLayout on each of those fragments as public and I tried to add the following above the AsyncGet fetch = ... line:
for (Fragment fragment : getSupportFragmentManager().getFragments())
{
if (fragment instanceof ChallongePlayers) {
((ChallongePlayers) fragment).swipe_container.setRefreshing(true);
} else if (fragment instanceof ChallongeMatches) {
((ChallongeMatches) fragment).swipe_container.setRefreshing(true);
}
}
Unfortunately, the first line of this code produces an error:
java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a null object reference
Why doesn't this work?
The collection returned by the getFragments() call has not been initialized yet and is null.
You can add an if check to make sure getFragments() does not return a null collection before iterating over it:
if(getSupportFragmentManager().getFragments() != null) {
for (Fragment fragment : getSupportFragmentManager().getFragments())
{
if (fragment instanceof ChallongePlayers) {
((ChallongePlayers) fragment).swipe_container.setRefreshing(true);
} else if (fragment instanceof ChallongeMatches) {
((ChallongeMatches) fragment).swipe_container.setRefreshing(true);
}
}
}
Related
I have a fragment in an activity that uses Firestore snapshot listener. When I first start the fragment, it works fine. But then if I navigate to another fragment and return, I get an empty snapshot. How do I get it to fetch the snapshot properly again?
Here is the query with the listener registration:
private void setupRecyclerView() {
if (mealplanRecycler == null) {
mealplanRecycler = mealplanView.findViewById(R.id.mealplan_recycler);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mealplanContext);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mealplanRecycler.setHasFixedSize(true);
mealplanRecycler.setLayoutManager(linearLayoutManager);
}
getMealplans();
}
private void getMealplans() {
String userId = (bundle != null && bundle.containsKey("userId")) ? bundle.getString("userId") : "";
Query mealplanQuery = firebaseFirestore.collection("Meal_Plans").whereEqualTo("userId", userId).orderBy("timeOfCreation", Query.Direction.DESCENDING);
registration = mealplanQuery.addSnapshotListener((value, error) -> {
toolbarProgressbar.setVisibility(View.GONE);
mealplanArrayList = new ArrayList<>();
if (error == null && value != null) {
for (QueryDocumentSnapshot document : value) {
Mealplan mealplan = document.toObject(Mealplan.class);
Mealplan updatedmealplan = updateTime(mealplan);
mealplanArrayList.add(updatedmealplan);
if (mealplanArrayList.size() > 0) {
tvAddMealplan.setVisibility(View.GONE);
ivAddmealplan.setVisibility(View.GONE);
}
}
if (mealPlanAdapter != null) {
mealPlanAdapter.setItems(mealplanArrayList);
mealPlanAdapter.notifyDataSetChanged();
} else {
String planId = (bundle != null && bundle.containsKey("planId")) ? bundle.getString("planId") : "none";
mealPlanAdapter = new MealPlanAdapter(mealplanContext, mealplanArrayList, planId);
mealplanRecycler.setAdapter(mealPlanAdapter);
}
mealPlanAdapter.setEditMealplanListener(this::onButtonPressed);
} else {
Log.d(TAG, "error is not null: " + Objects.requireNonNull(error).getLocalizedMessage());
toolbarProgressbar.setVisibility(View.GONE);
tvAddMealplan.setVisibility(View.GONE);
}
});
}
And this is how I am creating the fragment in Main Activity:
MealplanFragment fragment = new MealplanFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_right).replace(R.id.frame_container, fragment, null);
fragmentTransaction.commit();
A fragment's onCreateView is called only once when the fragment's view is being created. From then on it will be called again only if the view is destroyed and needs to be recreated. It is what function onCreate is for an Activity.
So, when you switch between fragments it is not called.
The solution is to place the listener registration code in a function that will be called when switching fragments.
You can try onHiddenChanged function:
#Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
}
else {
}
}
or
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
} else {
}
}
The above are deprecated in API level 28. So, you can also try setMenuVisibility:
#Override
public void setMenuVisibility(boolean isvisible) {
super.setMenuVisibility(isvisible);
if (isvisible){
Log.d("Viewpager", "fragment is visible ");
}else {
Log.d("Viewpager", "fragment is not visible ");
}
}
I have a switch that when you click it it populates a RecyclerView and trying to save the state through the lifecycle.
This is the xml
<Switch
android:id="#+id/reviewLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/eight_dp"
android:textColor="#android:color/white" />
This is the listener
private class ShowReviewsListener implements CompoundButton.OnCheckedChangeListener{
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if(isChecked == true){
showReviews();
isReviewButtonClicked = true;
}else if(isChecked == false){
isReviewButtonClicked = false;
}
}
}
This is what happens when you click it
public void showReviews() {
mReviewList.setHasFixedSize(true);
mReviewList.setVisibility(View.VISIBLE);
fakeView2.setVisibility(View.VISIBLE);
}
This is how i try to save it and retrieve it
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(INSTANCE_MOVIE_ID, mMovieId);
outState.putBoolean(IS_IN_FAVORITES, isInFavsAlready);
outState.putBoolean(REVIEW_BUTTON, isReviewButtonClicked);
super.onSaveInstanceState(outState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_detail);
mDb = AppDatabase.getInstance(getApplicationContext());
mToolbar = findViewById(R.id.toolbar);
mToolbar.setTitle(R.string.movie_details_title);
ButterKnife.bind(this);
if (savedInstanceState != null && savedInstanceState.containsKey(INSTANCE_MOVIE_ID)) {
mMovieId = savedInstanceState.getInt(INSTANCE_MOVIE_ID, DEFAULT_MOVIE_ID);
}
if(savedInstanceState !=null && savedInstanceState.containsKey(IS_IN_FAVORITES)){
isInFavsAlready = savedInstanceState.getBoolean(IS_IN_FAVORITES, false);
}
if(savedInstanceState !=null && savedInstanceState.containsKey(REVIEW_BUTTON)){
isReviewButtonClicked = savedInstanceState.getBoolean(REVIEW_BUTTON, false);
}
Log.d(LOG_TAG, "review button " + isReviewButtonClicked);
Intent i = getIntent();
if (i != null && i.hasExtra(EXTRA_MOVIE)) {
if (mMovieId == DEFAULT_MOVIE_ID) {
mMovieId = i.getIntExtra(EXTRA_MOVIE, DEFAULT_MOVIE_ID);
mMovie = i.getParcelableExtra(EXTRA_MOVIE);
populateUI(mMovie);
}
}
setTrailers();
setReviews();
if (isReviewButtonClicked) {
showReviews();
}
int movieID = Integer.parseInt(mMovie.getMovieId());
isMovieInFavorites(movieID);
reviewSwitch.setOnCheckedChangeListener(new ShowReviewsListener());
favoriteToggle.setOnCheckedChangeListener(new FavoriteListener());
}
Right now even though the isChecked is true, whenever i rotate the device, the views from showReviews() are staying hidden.
EDIT: Added full onCreate & image
Reviews handle
private class FetchReviewsAndTrailersTask extends AsyncTask<URL, Void, String[]> {
#Override
protected String[] doInBackground(URL... urls) {
URL searchReviewUrl = NetworkUtils.createReviewsUrl(mMovie.getMovieId());
URL searchVideoUrl = NetworkUtils.createVideosUrl(mMovie.getMovieId());
String jsonReviewString = "";
String jsonVideoString = "";
try {
jsonReviewString = NetworkUtils.makeHttpRequest(searchReviewUrl);
jsonVideoString = NetworkUtils.makeHttpRequest(searchVideoUrl);
} catch (IOException e) {
Log.e("Main Activity", "Problem making the HTTP request.", e);
}
return new String[]{jsonVideoString, jsonReviewString};
}
#Override
protected void onPostExecute(String[] jsonString) {
if (jsonString == null) {
fakeView.setVisibility(View.VISIBLE);
}
mTrailers = JsonUtils.extractTrailersFromJson(jsonString[0]);
mReviews = JsonUtils.extractReviewsFromJson(jsonString[1]);
populateReviewsAndTrailers(mReviews, mTrailers);
}
}
private void populateReviewsAndTrailers(List<Review> review, List<Trailer> trailers){
if (review.isEmpty()) {
reviewSwitch.setText(R.string.reviewLabelNone);
} else {
reviewSwitch.setText(R.string.reviewLabelExist);
fakeView.setVisibility(View.GONE);
mAdapter = new MovieReviewsRecyclerViewAdapter(MovieDetailActivity.this, mReviews);
mReviewList.addItemDecoration(new DividerItemDecoration(getApplicationContext(), DividerItemDecoration.VERTICAL));
mReviewList.setAdapter(mAdapter);
mReviewList.setVisibility(View.GONE);
}
if(trailers.isEmpty()){
trailersHeader.setText(R.string.trailersNA);
}else{
trailersHeader.setText(R.string.trailerHeader);
mTrailerAdapter = new MovieTrailersRecyclerViewAdapter(MovieDetailActivity.this, mTrailers);
mTrailersList.setAdapter(mTrailerAdapter);
}
}
I guess you forget to show reviews after rotating screen.
Try this:
if(savedInstanceState !=null && savedInstanceState.containsKey(REVIEW_BUTTON)){
isReviewButtonClicked = savedInstanceState.getBoolean(REVIEW_BUTTON, false);
if (isReviewButtonClicked) showReviews();
}
How to remove the fragment from his calling fragment ?
i have search this thing but i didn't get solution according to my requirement. In my application, there is one FragmentActivity which has the viewPager.
This viewPager contains 3 Fragments. For fragment I am using FragmentStatePagerAdapter.
Suppose there is 3 fragment: A, B, C; and D fragment C also contain a child fragment E.
I have call fragment E in the onCreateView() method and in the onDestroy() method of fragment C, I have remove the child fragment E.
So what is happening when I slid viewPager from C to B, and B to A - when I come back from A to B, now current displaying fragment is B. Now if I slid fragment C should be display, but in place of fragment C the child fragment of C, fragment E is displaying after then fragment E then fragment C is displaying now in this condition i have not seen Fragment E over the fragment C, the child fragment E is not interacting with viewpager but why it is added in viewPager,
i have try to destroy the child fragment E in onPause() and in onDestroy() method of C, but nothing is happening. Please any one help me.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MYDataManager.sharedHandler().changeLanguageConfiguration();
overridePendingTransition(R.anim.activity_open_translate, R.anim.activity_close_scale);
setContentView(R.layout.activity_myscanner);
appFlow = new ArrayList(Arrays.asList(MYConstant.kProfileMenuSettings, MYConstant.kScanner, MYConstant.kRestaurantListing));
viewpager = (ViewPager) findViewById(R.id.view_pager);
viewpager.addOnPageChangeListener(this);
viewpager.setOffscreenPageLimit(0);
reloadViewPager(1);
}
public void reloadViewPager(int currentItem) {
adapter = new FragmentStatePagerAdapter(getSupportFragmentManager()) {
#Override
public Fragment getItem(int position) {
return getFragmentWithPosition(position);
}
#Override
public int getCount() {
return appFlow.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
};
viewpager.setAdapter(adapter);
viewpager.setCurrentItem(currentItem);
}
private MYBaseFragment getFragmentWithPosition(int position) {
String screen = appFlow.get(position);
MYBaseFragment fragment = null;
if(screen.equals(MYConstant.kProfileMenuSettings)) {
myProfileSettingFragment = new MYProfileSettingFragment();
fragment = myProfileSettingFragment;
} else if(screen.equals(MYConstant.kScanner)) {
fragment = new MYScannerParentFragment();
} else if(screen.equals(MYConstant.kRestaurantListing)) {
myRestaurantListFragment = new MYRestaurantListFragment();
fragment = myRestaurantListFragment;
} else if(screen.equals(MYConstant.kRestaurantDetails)) {
myResraurantDetailsFragment = new MYResraurantDetailsFragment();
fragment = myResraurantDetailsFragment;
} else if(screen.equals(MYConstant.kCurrentRestaurantDetails)) {
MYQRCode qrData = MYDataManager.sharedHandler().getQRData();
if(MYUitilities.checkQRValidation(qrData)) {
fragment = new MYCurResDetails();
}
} else if(screen.equals(MYConstant.kSettings)) {
fragment = new MYSettingFragment();
} else if(screen.equals(MYConstant.kViewMenu)) {
fragment = new MYResCatListFragment();
} else if(screen.equals(MYConstant.kMenuCategoryListing)) {
fragment = new MYResCatListFragment();
} else if(screen.equals(MYConstant.kViewMenuViewPage)) {
// myResMenuViewPagerFragment = new MYResMenuViewPagerFragment();
// fragment = myResMenuViewPagerFragment;
fragment = new MYResMenuViewPagerFragment();
} else if(screen.equals(MYConstant.kReviewOrder)) {
fragment = new MYReviewOrderFragment();
} else if(screen.equals(MYConstant.kYourOrder)) {
fragment = new MYYourOrderFragment();
} else if(screen.equals(MYConstant.kSettings)) {
fragment = new MYSettingFragment();
} else if(screen.equals(MYConstant.kOrderHistory)) {
fragment = new MYOrderHistoryFragment();
} else if(screen.equals(MYConstant.kCheckout)) {
fragment = new MYCheckoutFragment();
} else if(screen.equals(MYConstant.kCallWaiter)) {
fragment = new MYCallWaiterFragment();
} else if(screen.equals(MYConstant.kYourProfile)) {
myYourProfileFragment = new MYYourProfileFragment();
fragment = myYourProfileFragment;
}
fragment.setFragmentInteractionListener(MYScannerActivity.this);
return fragment;
}
#Override
public void onPageSelected(final int position) {
if(currentPosition >= 0) {
final String previousScreen = appFlow.get(currentPosition);
final String currentScreen = appFlow.get(position);
System.out.println("previousScreen-" + previousScreen);
System.out.println("currentScreen-" + currentScreen);
if(previousScreen.equals(MYConstant.kYourProfile) && currentScreen.equals(MYConstant.kProfileMenuSettings)) {
appFlow.remove(MYConstant.kYourProfile);
adapter.notifyDataSetChanged();
viewpager.setCurrentItem(0);
}
if(previousScreen.equals(MYConstant.kRestaurantDetails) && currentScreen.equals(MYConstant.kRestaurantListing)) {
appFlow.remove(MYConstant.kRestaurantDetails);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kViewMenu) && currentScreen.equals(MYConstant.kRestaurantDetails)) {
appFlow.remove(MYConstant.kViewMenu);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kViewMenuViewPage) && currentScreen.equals(MYConstant.kViewMenu)) {
appFlow.remove(MYConstant.kViewMenuViewPage);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kViewMenuViewPage) && currentScreen.equals(MYConstant.kMenuCategoryListing)) {
appFlow.remove(MYConstant.kViewMenuViewPage);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kYourOrder) && currentScreen.equals(MYConstant.kViewMenuViewPage)) {
appFlow.remove(MYConstant.kYourOrder);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kReviewOrder) && currentScreen.equals(MYConstant.kViewMenuViewPage)) {
appFlow.remove(MYConstant.kReviewOrder);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kYourOrder) && currentScreen.equals(MYConstant.kReviewOrder)) {
appFlow.remove(MYConstant.kYourOrder);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kYourOrder) && currentScreen.equals(MYConstant.kViewMenuViewPage)) {
appFlow.remove(MYConstant.kReviewOrder);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kSettings) && currentScreen.equals(MYConstant.kProfileMenuSettings)) {
appFlow.remove(MYConstant.kSettings);
adapter.notifyDataSetChanged();
viewpager.setCurrentItem(0);
} else if(previousScreen.equals(MYConstant.kOrderHistory) && currentScreen.equals(MYConstant.kProfileMenuSettings)) {
appFlow.remove(MYConstant.kOrderHistory);
adapter.notifyDataSetChanged();
viewpager.setCurrentItem(0);
} else if(previousScreen.equals(MYConstant.kCheckout) && currentScreen.equals(MYConstant.kViewMenuViewPage)) {
appFlow.remove(MYConstant.kCheckout);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kCheckout) && currentScreen.equals(MYConstant.kReviewOrder)) {
appFlow.remove(MYConstant.kCheckout);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kCheckout) && currentScreen.equals(MYConstant.kYourOrder)) {
appFlow.remove(MYConstant.kCheckout);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kCallWaiter) && currentScreen.equals(MYConstant.kCheckout)) {
appFlow.remove(MYConstant.kCallWaiter);
adapter.notifyDataSetChanged();
} else if(previousScreen.equals(MYConstant.kRestaurantListing) && currentScreen.equals(MYConstant.kScanner)) {
if(MYDataManager.sharedHandler().isQRCodeScanned()) {
appFlow.remove(MYConstant.kRestaurantListing);
if(!appFlow.contains(MYConstant.kCurrentRestaurantDetails)) {
appFlow.add(MYConstant.kCurrentRestaurantDetails);
}
adapter.notifyDataSetChanged();
}
} else if(previousScreen.equals(MYConstant.kCurrentRestaurantDetails) && currentScreen.equals(MYConstant.kScanner)) {
} else if(previousScreen.equals(MYConstant.kMenuCategoryListing) && currentScreen.equals(MYConstant.kCurrentRestaurantDetails)) {
appFlow.remove(MYConstant.kMenuCategoryListing);
adapter.notifyDataSetChanged();
}
}
Fragment fragment = ((FragmentStatePagerAdapter) viewpager.getAdapter()).getItem(position);
if(fragment instanceof MYProfileSettingFragment) {
}
currentPosition = position;
}
You Please try these.
FragmentManager fragmentManager = getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.frame_container);
fragmentTransaction.remove(currentFragment);//remove current fragment
So what is happening when I slid viewPager from C to B, and B to A - when I come back from A to B, now current displaying fragment is B.
I had faced something before like you have now. I was registering and unregistereing a listener on fragments life cycle events. But in viewpager, even i switched to another fragment, the previously fragment never be destroyed, you can check
Before dive into your case, i wanna mention about 'off page limit'. So you cant set to zero. Check this link. So when you set 0, it defaults to 1
viewpager.setOffscreenPageLimit(0);
If im not missing something, in this case, when you switch from C to B
If you had visited D fragment before C, D will be destroyed, B will be created, C still will be living.
Assuming you coming from first case (C to B, and then B to A)
C will be destroyed, B lives, A will be created
Bottom line, with ViewPager you have min two fragments. One is you are currently interacting and second (screen off)
In my Android app I have a messages activity that is composed by three tabs (fragments: inbox, sent and deleted). I need to load data (received in JSON format and converted to String) in both tabs, but when I load the fragments app throws NullPointerException in the line where data is put in the bundle. I think that it's because the app hasn't received the information at the moment of its invocation.
To connect with the service provider i am using AsyncHttpTask library. Here is my code:
MessagesActivity.java:
public class MessagesActivity extends AppCompatActivity {
Toolbar toolbar;
ViewPager pager;
MessagesTabAdapter adapter;
SlidingTabLayout tabs;
CharSequence tabsTitles[] = {"Inbox","Sent","Trash"};
int tabsNumber = 3;
JSONObject inbox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.messages_activity);
//Elements initialization
...
adapter = new MessagesTabAdapter(getSupportFragmentManager(), tabsTitles, tabsNumber);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.messages_pager);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.messages_tabs);
tabs.setDistributeEvenly(true);
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.tabsScrollColor);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
}
public void updateInbox () {
String token = getSharedPreferences("Myapp", Context.MODE_PRIVATE).getString("token", null);
RequestParams params = new RequestParams();
params.add("token", token);
Client.get("get_inbox", params, new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
try {
inbox = response.getJSONObject("result");
} catch (JSONException e) {
//No messages
inbox = new JSONObject();
}
}
});
}
public class MessagesTabAdapter extends FragmentStatePagerAdapter {
...
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if(position == 0) // if the position is 0 we are returning the First tab
{
Bundle bundle = new Bundle();
bundle.putString("inbox", updateInbox().toString()); //HERE IS MY EXCEPTION!
MessagesInboxTab tab1 = new MessagesInboxTab();
tab1.setArguments(bundle);
return tab1;
}
else if(position == 1) // As we are having 2 tabs if the position is now 0 it must be 1 so we are returning second tab
{
//Here will go the same code as position==0
MessagesSentTab tab2 = new MessagesSentTab();
return tab2;
}
else
{
//Here will go the same code as position==0
MessagesTrashTab tab3 = new MessagesTrashTab();
return tab3;
}
}
...
}
How can I solve?
You are getting null inside your updateInbox() method because you return null at its end, I think you wanted to return something else but you forgot to write it :)
The following method, always returning a null value.
public JSONObject updateInbox () {
String token = getSharedPreferences("Myapp", Context.MODE_PRIVATE).getString("token", null);
RequestParams params = new RequestParams();
params.add("token", token);
Client.get("get_inbox", params, new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
try {
inbox = response.getJSONObject("result");
} catch (JSONException e) {
//No messages
inbox = null;
}
}
});
return null;
}
You should return inbox inside the try block.
I have an Activity that Displays Fragments one at a time , now each fragment load it data from server and keep fetching data in a list , the user can display another fragment in the activity by selecting an item in the Spinner that displayed in the ActonBar.
here is the code for the Activity
public class HomeActivity extends SherlockFragmentActivity .....{
private class ListInfo {
private String tag;
private Class<?> clss;
private Bundle bundle;
private Fragment fragment;
public ListInfo(String tag, Class<?> clss, Bundle bundle) {
this.tag = tag;
this.clss = clss;
this.bundle = bundle;
}
}
String[] naviStrings;
private HashMap<String, ListInfo> listMap = new HashMap<String, HomeActivity.ListInfo>();
private ListInfo mLastListInfo = null;
private int currentSelectedOptionInSpinner;
ChannelFragment fr;
#SuppressWarnings("unchecked")
#Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
Log.d("HomeActivity", "onCreate");
Log.d("onCreate bundle", "" + arg0);
setContentView(R.layout.test);
naviStrings = getResources().getStringArray(
R.array.action_bar_spinner_entries);
initializeList(arg0);
Context context = getSupportActionBar().getThemedContext();
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
context, R.array.action_bar_spinner_entries,
R.layout.sherlock_spinner_item);
adapter.setDropDownViewResource(R.layout.sherlock_spinner_dropdown_item);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getSupportActionBar().setListNavigationCallbacks(adapter, this);
getSupportActionBar().setSelectedNavigationItem(
currentSelectedOptionInSpinner);
}
private void initializeList(Bundle args) {
ListInfo listInfo = null;
// add first Fragment
listMap.put(naviStrings[5], (listInfo = new ListInfo(naviStrings[5],
AboutUsActivity.class, args)));
addFragmentToList(this, listInfo);
listMap.put(naviStrings[3], (listInfo = new ListInfo(naviStrings[3],
Fragment1.class, args)));
addFragmentToList(this, listInfo);
listMap.put(naviStrings[2], (listInfo = new ListInfo(naviStrings[2],
Fragment2.class, args)));
addFragmentToList(this, listInfo);
listMap.put(naviStrings[1], (listInfo = new ListInfo(naviStrings[1],
Fragment3.class, args)));
addFragmentToList(this, listInfo);
listMap.put(naviStrings[4], (listInfo = new ListInfo(naviStrings[4],
Fragment4.class, args)));
addFragmentToList(this, listInfo);
if (args != null) {
Toast.makeText(this, "args is not null", Toast.LENGTH_SHORT).show();
// set the current selected index in the ActionBar spinner
if (args.getInt(
ApplicationMetaData.IntentData.LAST_SELECTED_ITEM_SPINNER,
-1) > -1
&& args.getInt(
ApplicationMetaData.IntentData.LAST_SELECTED_ITEM_SPINNER,
-1) < naviStrings.length) {
Toast.makeText(this, "selected is not null",
Toast.LENGTH_SHORT).show();
currentSelectedOptionInSpinner = args
.getInt(ApplicationMetaData.IntentData.LAST_SELECTED_ITEM_SPINNER);
} else {
currentSelectedOptionInSpinner = 2;
}
} else {
currentSelectedOptionInSpinner = 2;
}
onNavigationItemSelected(currentSelectedOptionInSpinner, 0);
}
private static void addFragmentToList(SherlockFragmentActivity activity,
ListInfo instanse) {
// check to see if we already have a fragment for this tab , probably
// from a previously save state.
// if so deactivated it ,because our initial state is that a tab is not
// shown.
String tag = instanse.tag;
instanse.fragment = activity.getSupportFragmentManager()
.findFragmentByTag(tag);
if (instanse.fragment != null && !instanse.fragment.isDetached()) {
FragmentTransaction ft = activity.getSupportFragmentManager()
.beginTransaction();
ft.detach(instanse.fragment);
ft.commit();
activity.getSupportFragmentManager().executePendingTransactions();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(
ApplicationMetaData.IntentData.LAST_SELECTED_ITEM_SPINNER,
currentSelectedOptionInSpinner);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
Log.d("onNavigationItemSelected", "" + itemPosition);
if (itemPosition == 5) {
Intent i = new Intent(this, AboutUsActivity.class);
startActivity(i);
return true;
}
Log.d("fragment data", listMap.get(naviStrings[itemPosition]) + "");
ListInfo newtItem = listMap.get(naviStrings[itemPosition]);
if (newtItem != mLastListInfo) {
FragmentTransaction ft = this.getSupportFragmentManager()
.beginTransaction();
if (mLastListInfo != null) {
if (mLastListInfo.fragment != null) {
ft.detach(mLastListInfo.fragment);
}
}
if (newtItem != null) {
if (newtItem.fragment == null) {
// create and add
newtItem.fragment = Fragment.instantiate(this,
newtItem.clss.getName(), newtItem.bundle);
ft.add(android.R.id.content, newtItem.fragment,
newtItem.tag);
} else {
ft.attach(newtItem.fragment);
}
}
mLastListInfo = newtItem;
ft.commit();
this.getSupportFragmentManager().executePendingTransactions();
return true;
}
return false;
}}
now when i navigate from one fragment to another lets say from Fragment1 to Fragment2 when i return back to fragment1 it preserve it state and does not have to load it data from the beginning , but if i start a new Activity from the home Activity the system destroy the Activity and the Fragments in it , is There a way to preserve these Fragment note when i rotate the Home Activity nothing happened , only if i start a new Activity ??????
UPDATE
in all of the Four Fragment i make in the onCreate setRetaineInstance(true);
One option is to override saveInstanceState in your Fragments and/or Activites in order to persist data and later retrieve it from the Bundle that gets passed into onActivityCreated/onCreate.
If you are dealing with large sets of data, you may be better off using another persistence mechanism like the SQLite database