How to show DialogFragment from within the onLoadFinished method of LoaderCallbacks - java

I receive an exception when trying to show a DialogFragment from within the onLoadFinished method of a Fragment that implements the LoaderCallbacks interface. Basically I am using the LoaderCallbacks to get some data from a rest service and then on the onLoadFinished I am trying to show a custom DialogFragment that contains a ListVeiw to allow the user to make a selection. Everything works great except when I try to launch the dialog from within the onLoadFinished. How can I accomplish this..and is this the correct approach to the problem.
Here is an example of what I am trying to do:
public class EventFragment extends Fragment implements LoaderCallbacks<someresponse> {
#Override
public void onLoadFinished(Loader<someresponse> arg0, someresponse data) {
//an exception is generated when trying to launch a dialog fragment from
//within the onLoadFinished
FragmentManager manager = getFragmentManager();
ListViewDialogFragment dialog = ListViewDialogFragment.newInstance(data);
dialog.show(manager, "event_list_dialog");
}
}
Thanks!

So after some research, I have determined that my approach was incorrect. You should never try to launch a new fragment from within the onLoadFinished method of an LoaderCallbacks async task. The framework tries to keep you from doing this because the state of the currently running fragment or activity, that implements the LoaderCallbacks is indeterminate and therefore not guaranteed to be there when the async task finishes.
Additionally trying to separate a processing dialog state and data display state into two separate fragments is a bit counter to the MVC design pattern that the android framework supports. That said, my new approach consisted of dynamically changing the view for the fragment implenting LoaderCallbacks to hide or show a specific linear layout, one for the process indicator and one for the display of the data. This approach left me modifying an existing fragment instead of launching a new one which worked out great.
Here is a link to the discussion that finally gave me clarity.
https://groups.google.com/forum/#!topic/android-developers/dXZZjhRjkMk/discussion

The approach you define is quite good, except one case - what will happen if your activity had already gone from the screen, when loading operation got finished? How it will show dialog in this case?
So generally, I would appreciate if you'll tell which exactly exception did you get.
However, as a general approach, it can be useful to check is the activity holding the fragment is still on top or even was it finished or not.
Even better - you should consider cancelling all background operations when activity/fragment is destroying, in this case you'll have no problems with showing dialogs.
Good luck!

Related

How to display data from a Loader using Toast

I've a simple Activity (class MainActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor>)
Also I've a simple layout with a text box and a button.
Just to keep it simple, lets say I've a Loader that loads data from a HashMap<String> (which is already populated) and I've intialized/configured LoaderManager and CursorLoader appropriately.
Now I'd like to display the content of HashMap using a Toast upon clicking on the button, (which is bound to onClickRetrieveData(){} in Activity)
Any hint on how to do that?
UPDATE: I understand how to display data on Toast (once I have the data), but my question is more of the line of retrieving data from the Loader inside onClicRetrieveData().
It's hard to tell whether you're asking how to kickstart the Loader to get it loading or what to do when it is done. If we assume that you mean you want to start loading the data when the button is clicked and calls onClickRetrieveData(), then you'll do something like this:
#Override
void onClickRetrieveData(View v) {
getLoaderManager().initLoader(MY_LOADER_ID, null, this);
}
Then, your implementation of the LoaderCallbacks.onCreateLoader() will need to actually create an instance of your Loader. The framework will then kick it off and run it appropriately. When it is done, onLoadFinished() will be called and you'll have your results. From there you can do as you please: update an Adapter, pop up a Toast, etc.
Here's a primer on Loaders you may find helpful: http://po.st/xHoVMf

android -what approach to be used for some java code that repeats in many activities

I have an app that has a top menu as shown in the fig below. This is almost constantly used in all activities. For layout I have defined it in a single xml file and use <include>to include it in every layout file.I want to know if there is a way in java coding to avoid declaring all the imageButtons, and then using findViewById and onclick events for them , in each activity. The top four icons will act as menu and be available in all layouts and activities
First of all, what you are trying to achieve is against the android standards and this could affect the user experience for Android users. Instead, add the menu items on the action bar.
Anyway, you can achieve what you are looking for by defining a base class (named it like ActivityBase) and do all the initializations and listeners registrations on it. Then, extend from that base class. Bear in mind that each activity will have its own instance of the views of the base class and the state will differ from activity to another.
Although you have accepted an answer I disagree that the Application class should be used to host global methods. It can be used for maintaining global state but that's a different matter.
As others have said, use inheritance by creating a base Activity class then extend that for all of your other Activities. To make things easier, however, you can define the onClick method to be used for each of your buttons in the layout file itself by using (for example)...
android:onClick="myOnClickMethod"
As long as the base Activity defines a public method called myOnClickMethod (or whatever method name you choose) with a void return and which accepts a View parameter it will work without the need to implement View.OnClickListener and without having to set the listener in Java code. Example
public class MyBaseActivity extends Activity {
public void myOnClickMethod(View v) {
// Get the resource id of v and use switch / case to perform action needed
}
}
That's all you need.
Write it only in the first activity. Extend it to the other activities instead of extending with android.app.Activity.
Eg:
public class SecondActivity extends MainActivity{
}
Put that method in MyApplication class which extends Application. So, that it can be accessible by multiple activities.

Detecting when activity changes

I am trying to add a save dialog to an Activity.
If you press back, I already have captured it and added a save dialog box.
As I have a generic action bar, is there a way to capture the change of activity event without hardcoding it into the activity change itself?
I Googled it a bit and found no luck, onDestroy and onStop don't seem to do what I want.
If you want to know whenever the Activity ceases to become visible (for whatever reason), override onPause (see http://developer.android.com/reference/android/app/Activity.html).
As an aside, as a user, I would want this behaviour - if I move away from an Activity without pressing the back button or quit, I am hoping that it will handle everything silently - ie you use onPause (or alternatives) to store things so that when the activity resumes it has everything as I left it.
One way you could do this would be write a class which inherits from Activity and implement the behavior in that class. Then simply inherit this class for all your activities.
You could write one class which implements the save behaviour
class SaveActivity extends Activity {
//...
#Override
public void onBackPressed() {
// common behaviour you want
}
}
Then in your activities you could do this
class MyActivity extends SaveActivity {
// code for this activity
}
onPause() might be what you should be looking at. It is called when any activity comes onto the top of this Activity.

android finish current activity causes app close

I am executing maswebview class and I would like to finish only this activity. I tried maswebview.this.finish() but when executed, app is been closed. Then if I set a new view for the tab content, it is loaded properly and webviewmas dissapears but just for a while, then appears again fitting fullscreen. How to finish maswebview completely? ThanK you
public void onClick(View arg0)
{
/*
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
startActivityForResult(intent, 1);
Intent intentmas = new Intent (maswebview.this, mas.class);
intentmas.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intentmas.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intentmas.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentmas.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
View vista = getLocalActivityManager().startActivity("maswb", intentmas).getDecorView();
setContentView(vista); */
maswebview.this.finish();
Do you have any other activities of your app in the stack by the time you call finish()? If you don't, you'll want to start the desired activity instead of finishing the current one.
But actually it seems to me that you're trying to accomplish something that can be done simpler. Can you provide more info on the task at hand and your app structure you're trying to go about it with?
From what you said, it seems like you have tabbed UI and you're trying to show a webview in one of the tabs, then hide it.
First, I don't see why you want the webview in a separate activity. Seems to me you could just have it in layout of one of the tabs and just call setVisibility(GONE) to hide it.
Second - and this is important - looks like you're trying to implement tabs the old way - TabWidget, TabHost, etc. Since Honeycomb has been released, there's much more convenient way to implement tabbed UI - Action Bar Tabs and Fragments - that approach is much more convenient and will render your webview problems obsolete: there's a thing called WebViewFragment which is basically a WebView but smarter - it will handle its own lifecycle with minimum effort required from you (i.e. pause when removed, resume when added). It will take some effort to study up on Fragments, but it's well worth it. You can get Fragments API for pre-Honeycomb android sdks as a static library - it's called android-support-v4 and you can download it in Android SDK Manager.
Are you calling "maswebview.this.finish();" before the new Activity is started?
Also if you want to just start this new activity without having the old activity in existence then you can add android:nohistory="true" to your manifest.xml. This will cause the current activity to be the only activity in the queue.
See HERE
You need to provide a little more information for us to better understand what exactly is going on.
I hope this helps.
Try following code
#Override
public void onBackPressed() {
if(childView != null && parentLayout.getChildCount()==2){
childView.stopLoading();
parentLayout.removeViewAt(parentLayout.getChildCount()-1);
if(webView.getVisibility() == View.GONE)
webView.setVisibility(View.VISIBLE);
}else{
super.onBackPressed();
}
Do you have a parent activity which is launching this one? If yes make sure you don't call finish() after launching maswebview, that way the parent activity will remain in the stack. Once maswebview would exit, onResume would be called for your parent activity.

How to use Android Fragments?

I'm looking at some demo code that shows how to use a Fragment Adapter (Tab Adapter in this case). I'm curious as to what exactly the instantiate() method does. I see it used in the following demo code on this page:
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
(see the getItem() method within the TabsAdapter class)
If I'm reading the demo code correctly, every time a user clicks on one of the tabs, a new Fragment is created? And thus the fragment starts the entire life-cycle again (onAttach()...onCreate()... etc)? This sounds awfully inefficient. I would think that the fragment that will represent the content for each tab should be instantiated only once (perhaps in the addTab() method), and then saved into some collection where it can be fetched when getItem() is called.
Please correct me if I'm mistaken in any of this. I'm trying to better understand how to manage fragments.
My money would be on that the setCurrentItem() function doesn't actually destroy the existing Fragment being shown in that tab. Otherwise there's really not much of a reason for the adapter to have a List of available tabs. Likely, when you switch from one tab to another, setCurrentItem() just detaches the UI from the currently active Fragment (or calls its onPause() method) and then re-attaches the UI for the newly selected Fragment (or calls its onResume() method).
But, if you're in doubt, you could read the source :)
Hope it helps,
David
I was able to find an explanation for my question here

Categories

Resources