I have a gridView which I populate with aJsonObject gotten from a website, with a CustomAdapter (baseadapter).
I'm using Volley library to manage the HTTP requests (it works fine, as far as I tested).
When I launch the app, the grid is populated correctly (50 Items).
But if I exit the app -with finish()- and then click on the launcher icon, the list stays empty (the http request is successfull, but getView is never called).
Relevant Notes:
I first had a similar problem for all instances (which I solved by properly setting the visibility of the gridview container -a RelativeLayout- to VISIBLE)
The getCount() function is always returning 50 items (which is the correct value).
After some tests, the 2nd time I launch the app the gridview container -and the gridview itself- has visibility set to 0 (not by me)
This is happening in all android versions.
Important: if I Force Stop the app, then launch it, the contents load just fine (the same if I clear cache).
Questions:
If getCount() is returning 50, why is getView not being called?
Why is my element "gone" even if I forced it to visible?
Not pasting code, as I think this is a conceptual problem, and not a coding problem, by now.
Thank you in advance, Droiders.
I temporarily solved this issue by killing the android process when the user exits/finishes the app,
public void onDestroy() {
super.onDestroy();
android.os.Process.killProcess(android.os.Process.myPid());
}
but I don't really like this workaround.
Any suggestions on how to solve the problem with more elegance will be appreciated.
Related
I have a MainActivity that extends SherlockActivityFragment. This activity holds some fragments and a menu. Each menu item leads to new SherlockActivities. One particular SherlockActivity when it is loaded contains a carousel, that moves extremely slow.
However, once the orientation changes this carousel performs perfectly. I know that the Activity is reloaded on orientation change. But I have no idea what could start this to begin with, or even where to start looking.
Has anyone come across any similar issues? What did you do to profile the issue and what was your fix?
If you can think of relevant parts of the code (eg onCreate etc) please ask and I'll post it. Each activity has about 150 - 200 LoC)
Edit:
Here is the intent that I am using to start the SherlockActivity in question:
Intent rankIntent = new Intent(context, RankActivity.class);
rankIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(rankIntent);
break;
I've read that on orientation change onDestory() is called followed by onCreate. This makes me think that maybe some resource is freed that wasn't initially available. But the flag in the intent is intended to clear the backstack and any resources with it.
I've also tested with using the finish() method just before loading the new activity with no improvements.
This seems like a far reach but I recently had a problem I'd say could be similar.
I learnt that Android doesn't handle scaling images particularly well - could it be that the images are scaled before you change the orientation and not scaled once you do?
Answering the 2nd part of your question: since my app doesn't perform any resource-needy logic operations and is based on its UI, what I did was comment out some of its elements one at a time to see if it helps; that's how I found out an ImageView that was scaled up in my case.
I have this problem for over a week now and after going through dozens of topics here and on google, I still don't have an answer.
The issue is that I am dynamically loading data to long ListView, so the initialization doesn't last for ages. After changing phone orientation ListView is beeing resized and have empty elements inside (thats ok). So i thought that OnConfigurationChanged event will handle this. Unfortunately it's fired before widgeds are resized, so still I have empty list. And here is my question: Is it anyway to get an event (or Listener) that will fore after the widged is resized and drawn?
I already have in manifest:
android:configChanges="keyboardHidden|orientation|screenSize
And there is no way to turn it "off", because loading takes few seconds and I don't want to have a few seconds lag while chenging phone orientation.
P.S. Sorry for any language mistakes ;)
yes. You can use setOnGlobalLayoutListener() that will listen and you use a callback once layout is completed
Also on screen rotation, activity should be destroyed, recreate, so your loading should restart. Are you doing something strange?
I do this in one of my fragment :
root = inflater.inflate(R.layout.fragment_booking_accepted, null);
root.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Dbg.e(TAG, "- On Layout Completed ! ");
// If you need this to be called again, then run again addOnGlobalLayoutListener.
// root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
isLayoutCompleted = true;
// YOU write here all the coed you might need. }}}} close brackets
Edit :
Most people think it's horrible to not let android do its job: destroy and recreate when screen rotates. But you can do what you want.
Loading an empty list view is very light. It's impossible it takes few seconds to load the layout. You HAVE to load the layout and your listview with a spinner to let the user know what his phone is doing (loading). Once data is loaded, notify data change to the adapter.
does it change your point of view? ask me, if I know, I'll try to answer.
I have a list of orders in one fragment. In a second fragment, I display the detail of the order, and I use a third fragment to display the buttons that change the status of the order.
In the list, each order is displayed with a background color that indicates its status, for example green for a completed delivery.
When in landscape mode, both the detail and list are shown. In portrait mode I use two separate activities.
This all works fine, up until I change the status of an order. I can't find a way to get the list to update.
As I understand it, what needs to happen is the adapter needs to have its notifyDateChanged() method called. I've tried calling it directly from the method that processes the button click, I've tried an asynctask, and I've tried a handler. My debug methods show that the call is happening, but the list doesn't get updated.
It's possible I'm doing something completely bone-headed, but I've double and triple checked things. I suspect there is some key element I don't understand. I hope someone else does and will tell me what I'm missing.
I had some code posted, but it was clearly wrong. Not sure what code to post, since I think this is more a conceptual than coding issue.
If you want to update a view, try to use :
Thread + Handler
AsyncTask
What I discovered, through the helpful comments of other posters, is that my problem wasn't that the adapter wasn't getting the notifyDataChanged() call on the correct thread. I put in debug code that proved that. The problem was that the background of the listview item was based on a change in the underlying data itself, so the real answer was to get the Adapter to refresh the Cursor. I made some changes. I modified the AsyncTask I was using to notify the adapter. Now the AsyncTask gets a new cursor and calls adapter.changeCursor(cursor) with the result. The AsyncTask is called from the MainActivity (which hosts both the list and detail fragments) when the status is changed. It's also called in the onResume() portion of the ListFragment code, so the list will be updated properly when coming back from the detail fragment. Works great.
A strange behavior I'm tearing my eyes on since early this afternoon, I'm givin up understanding but perhaps someone has an idea (yeah, I'm a beginner, some PROBABLY has an idea ^^).
Situation :
MainActivity.java (first one to be called, only one of interest here)
public ExpandableListView listClubs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listClubs = (ExpandableListView) findViewById(R.id.expLstMainClubs);
AppGlobal.CreateDistricts() ;
ELVAdapterDistrictsClubs adapter = new ELVAdapterDistrictsClubs(this);
listClubs.setAdapter(adapter);
}
it's the only code in the class. Basically, I'm filling an ExpandableList with an adapter that relies on what's created in the CreateDistricts() method (creates business objects, Districts containing Clubs containing Members, Events, etc.).
Basically (again ^^), everything runs fine, on first start the ExpList works as expected, as well as the rest of the app. If I hit the back button from the MainActivity, however, and rerun the app, a "strange" (to me at least) behavior occurs :
The ExpList is loaded twice in a row - first one with the data, works fine, and just below a duplicate (with the same 2 Groups, i.e. here the only two Districts in my sample data), which doesn't work at all (if you try to expand it, it crashes the app).
Frankly, I'm lost - I've tried some things on the various on[Pause/Stop/Destroy/Start/Resume] etc. to no avail (therefore, there is yet nothing done on this side, no override, as it seems not to bring anything good).
As the onCreate will after the onDestroy load the bundle, it should load the ExpList as it were, and in this case there might be a conflict between the "old" groups/children and the actual ones (currently, data is simulated, but will afterward come from a remote data source), and I haven't decided yet what the best "save" behavior is, i.e. if I should find a way to obliterate the ExpList onDestroy in order to be sure it's 100% recreated anew (and how does one do that ?) and start from scratch, or if I could use the ExpList as is, while updating it's content, in order not to lose the previous selection. It may be irrelevant to complicate matters in order to do that, the first list being not so big and quite quickly used to reach the second activity...
Anyway, I suspect it comes from around that part, the bundle load after destroy and rerunning, does it reload the ExpList as is and then I add things instead of first deleting ? What I found confusing is that the next activity (reached simply by clicking one of the items of the ExpList) displays a similar ExpList (filled with Months and Events per Month for the selected Club), and doesn't present the same strange behavior after a destroy... and both have an almost identical ExpList declaration in their original xml layout so... well, perhaps tomorrow morning I'll see the light, but if anyone has an idea, feel free :D
The more I write, the more I think I should first clear the ExpList but... I don't see how exactly. I've tried
listClubs.removeViewsInLayout(0, listClubs.getCount()) ;
but it just doesn't seem to do anything.
Thanks in advance
Nothing related to Android behavior - I was recreating everytime the whole set of BO behind if the base ArrayList of Districts was not null... instead of simply getting out of the method, but it raises another question - how was the state of this ArrayList, which is declared in a subclass of Application serving as Application in my manifest ? I'll have to make some tests about that...
I am having an issue with updating AppWidgets and a confluence of limitations/bugs in android is preventing me finding a workaround.
My app widget is themeable so I need to be able to update the imageviews on it at runtime (as well as the textviews and intents). There are up to 9 imageviews that I am updating but the size of the graphics I'm using are fairly modest (max 11kb pngs). The total size of data I am pushing through the RemoteViews object should be under 100kb, well within the limit of 1mb. I think that actual drawable resources on screen end up being larger in size than the original pngs, but 10% of the limit seems reasonable enough to account for that. However, with certain phones and launchers, I am getting "FAILED BINDER TRANSACTION" errors.
There are two solutions that I have found for this:
1) Use setImageViewUri (which calls setImageURI) instead of setImageViewResource with the RemoteViews object, this gets rid of sending drawables through the RemoteViews object and loads the image from URI instead. Solves the memory error (see https://groups.google.com/forum/#!topic/android-developers/KKEyW6XdDvg/discussion )
2) Divide the updates to the app widget into multiple RemoteViews calls. So I update 3 of the images, call updateAppWidget, create a new RemoteViews object, update the next 3 images, call updateAppWidget, etc.
The problem with the 1st approach is that it only works for medium density devices. All other devices scale the images incorrectly due to a bug in the android codebase (see bug report: http://code.google.com/p/android/issues/detail?id=22590 )
The problem with the 2nd approach is that when the screen orientation changes, android destroys and recreates widget views using the last RemoteViews call which it stores in some secret place. This meams the appwidget doesn't get fully redrawn because I split my RemoteView calls up and the widget ends up unusable. There appears to be no reliable way to figure out when android is destroying and recreating the appwidgets - onConfigurationChanged in the service doesn't always fire and no Activity level call is ever made (ie. onUpdate, onReceive) that I can find. In order for the widgets to be able to be redrawn fully and correctly on orientation change, I can only use one RemoteViews (updateAppWidget) call so this solution won't work.
Does anyone have any idea how to work around this? I'm wondering if it'd be possible to implement my own RemoteViews that called a non-buggy setImageURI function (in a custom ImageView class) so that the scaling happened correctly. It seems like a lot of work just update a few widgets and I am not sure android will let me extend RemoteViews/ImageView that way.
Is there anyway to intercept android when the screen orientation changes and force it to redraw the whole widget?
Would love to hear any other suggestions or workaround ideas! Thanks.
I've encountered the same problems when developing collections' AppWidgets. Many times the following would happened:
On rotation, the ListView entirely dissapeared;
The button listeners (actually called PendingIntents) stopped responding;
Changes in images via setImageViewResource didn't get updated;
.. and so on. I came to the same conclusion as you did: android destroys and recreates widget views using the last RemoteViews call which it stores in some secret place. After acknowledging that, it was a question of fine-timing the calls to AppWidgetManager.getInstance(context).updateAppWidget() because I wanted to disable the clickListeners (or PendingIntents) after telling the ListView to refresh itself (it was a network operation of calling web-services and retrieving a non-trivial amount of data) and wanted to enabled the listeners after the ListView finished loading while maintaining the RemoteViews fully loaded in order to handle a rotation.
I was this close to giving up and using as an alternative..
Is there anyway to intercept android when the screen orientation changes and force it to redraw the whole widget?
.. a service that does intercept Android rotation changes, unlike an AppWidget. If you're running out of options, I'd suggest you'd try it out:
public class MyWidget extends AppWidgetProvider {
#Override
public void onConfigurationChanged(Configuration newConfig)
{
// insert code here
}
}
Find out more about the service here in StackOverflow.