load data into an array using for loop android - android

I am trying to populate an array of image urls from Post class but the activity returns a blanked page. am i doing it right. sorry am learning android don't know much.
ArrayList PostDetails = new ArrayList();
for (int index=0;index<imageUrls.length;index++){
imageUrls[index]=PostDetails.get(index).getImag();
}

You should wait till the task is completed, you can put the last part in onPostExecute method..
protected void onPostExecute( ) {
String[]imageUrls= new String[PostDetails.size()];
for (int index=0;index<imageUrls.length;index++){
imageUrls[index]=PostDetails.get(index).getImag();
}
}

The answer by Nunu is correct, but I would like to expand on it a little. The assumption is that loadingTask is an AsyncTask, thus when you call execute the code within doInBackground will execute asynchronously. The code where you create and populate the array will execute in parallel to your population of PostDetails, which I assume is populated within the loadingTask. Since the array loop will execute very quickly, it will have completed long before the network operation performed by loadingTask. Thus your page is blank because you have looped through the array before PostDetails has been populated.
The solution is just as Nunu suggests, which is to move the population of the imageUrls array into the onPostExecute method of your AsyncTask. Also, any UI manipulation that uses this array should also be moved into onPostExecute.

Related

Progress Dialog is paused

Here it is.
Before fetching the data, creating the progress dialog and showing it now fetching data from server using volley library. It working fine. After that I need to send the data to local database as follow:
if (responseStatusCondition) {
JSONArray jsonArray=response.getJSONArray("response");
for (int i=0;i<jsonArray.length();i++) {
JSONObject childJSONObject = jsonArray.getJSONObject(i);
// Set the flag bit to 1 since data is already at server
long result = bloodPressureDatabaseFragment.insertIntoBloodPressureDetails(
childJSONObject.getInt("systolic"),
childJSONObject.getInt("diastolic"),
childJSONObject.getLong("timestamp"),1 );
}
}
Now problem is this, since the fetching part is happening in background is ok. But the insertion data into db part is happening on the Main UI which leads to pause the progress dialog. Is there any way to solve this problem.
I have done insertions part through the AsynckTask. Is there any alternative to do this task. I also read we can this through the use of Async-Await.
It is good if you please comment the reason of downvoting the question.

Displaying a large table with an AsyncTask

I have a method that takes data in a very large array and displays a very large table on the Display. The table is so large that the screen goes blank for awhile. Can I put the display method inside an Asynctask and display a progress bar until the display method is complete?
No, you can't access Views from background. You can load data into array in a background thread (so it won't block UI during load) and then use this array in an adapter for ListView. I can answer you with more details if you post your code
As mentioned by Chaosit you can't access the UI from a background thread.
consider loading the data in an async task, for loading the table to the UI try to render it row by row. if you are using a listView there are techniques to add/edit cells without rendering the whole table .
i used the same techniques when dealing with large number of PINs that needed to be rendered as the user move the Map .i load some of them and render them 1 by 1 to the UI .
The best way to load a big volume of data is to show a ProgressBar in onPreExecute(), load your data in doInBackground(...) and set the visibility of the progress bar to GONE in onPostExecute(Boolean success).
Another nice way to do it is display a Dialog calling .show() in onPreExecute() and dismiss it in onPostExecute(Boolean success), maybe updating the Dialog message in the onProgressUpdate(String... message).
Just remember that you cannot update or change your UI in doInBackground(...), but you can in onPreExecute(), onPostExecute(Boolean success) and in onProgressUpdate(String... message).
If the data is coming from a the database (or from a remote source) then consider using Loaders/CursorAdapter - to build your ListView. This is a very efficient way of loading data.
If you're reading Array data from a file then try to break down the data - and just select the data that you're displaying on the screen, rather than reading all the data from the file, and try to render item that will not be displayed - Then you can use AsyncTask or a Thread(and Handler) to update your table.
As the others have mentioned, only the main thread can update the UI.
Surely not all the data is shown at once!
Have a look at the Loaders guide. It will allow you to load a large data set, and display only part of it, reducing load times.
Said functionality can be achieved using asynctask as
class TestAsync extends AsyncTask<Void, Integer, String>
{
protected void onPreExecute ()
{
//Start showing progress bar here ...
}
protected String doInBackground(Void...arg0)
{
// Do long running operation here ...
return "You are at PostExecute";
}
protected void onPostExecute(String result)
{
// Start displaying data in your table view and dismiss the progress bar
}
}
Call it like this in your activity:
new TestAsync().execute();

Rx java android chaining requests

As I am learning rx java, I have found another problem that I am very curious about.
I am trying to create load more with list and rx java android extension using Retrofit.
So I have created stream to my List and calling onNext whenever I need more data, this means (Its crucial) 2-3 at the very beggining, I am loading data at batches 10 per request, at first I do have to load them 3 times, one after another, then on every value I do apply a scan method to increase my value
.scan(0, new Func2<Integer, Integer, Integer>() {
#Override
public Integer call(Integer integer, Integer integer2) {
return integer + 1;
}
}
Then doing request using retrofit that returns list of Strings and changing adapter data
of course I am calling
.subscribeOn(Schedulers.newThread().observeOn(AndroidSchedulers.mainThread()
But I am getting an exception
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.
It seems that adapter data is trying to be modified from background thread, however I have checked, whenever I call adapter method to modify data I am on the main thread. This problem does not occur when I am loading single batch, only when trying to load few and well I cant figure out why its happening. Next side effect is that sometimes second batch is beign loaded before first. I have been messing around with blocking obvservable but without any result.
Thanks for any tips.
Edit
Pseudo code on my logic:
CreateListObservable
.scan(increase value by 1)
.flatMap(download batch of values)
.scan(add new batch to existing one)
.subscribe(Schedulers.newThread)
.observeOn(AndroidSchedulers.mainThread)
.subscribe(data -> adapter.changeData(data)
Edit 2
It seems than when I add some sleep between changing data (1s) this error dissappears, weird
Have you tried copying the output array before passing it to the adapter? If it is the array that scan retains, further requests may be editing the content of the array on the background thread due to the scan.
.subscribe(data -> adapter.changeData(data.copy())

Images in ListView search results

I have a ListActivity that launches a task to hit a web service and display the results in a ListView. Each one of the results has an image ID attached to it.
I wrote a method that will get the image IDs of the rows displayed on screen (firstVisiblePosition() to lastVisiblePosition()) and launch a task to query another web service to get the images to display for those items. I call this method when the list's scroll state becomes SCROLL_STATE_IDLE. This makes it so the user can scroll and the task to get the images for the visible rows does not execute until the scrolling stops, preventing it from looking up images for off-screen rows.
My issue is that when the results initially show in the ListView, I can't find a good way to call my method to look up which image IDs to query for. Apparently, calling this method right after calling setAdapter does not work (I'm guessing because some of the ListView's work happens asynchronously). I am using multiple Adapter's (for reasons not pertinent to this post), so I need a good way of waiting for the list items to show before I call my method to get the IDs.
Any ideas?
After you've set the adapter or called notifyDatasetChanged() on the adapter, add your "load images" code to the list's post queue as a Runnable:
list.post( new Runnable() {
#Override
public void run() {
//do stuff
}
});
If I'm understanding your question right, you're having trouble loading images over the net and performance issues; if so,
I would create a simple image cache in my Adapter such as a local but global HashMap:
private HashMap&ltString, Drawable&gt imgCache = new HashMap&ltString, Drawable&gt();
then in my getView() method, I would asynchronously (using a Thread and a Handler) load the images and save loaded images in my imgCache by assigning position as the key and loaded images as Drawables.
final Handler h = new Handler() {
public void handleMessage(Message msg) {
if(msg.obj != null) {
Drawable drawable = (Drawable)msg.obj;
image.setImageDrawable(drawable);
image.postInvalidate();
image.requestLayout();
imgCache.put(cacheKey, drawable);
}
}
};
loadImage(myImageView, imageURL, h); // threaded method which loads the images from net
also, in my getView() method I would first ask imgCache to see if the image already exist before loadImage is called.
This should optimize your list and rescue you from using multiple Adapter etc.
Hope this helps,
-serkan

Displaying large tables without choking UI thread

I have a table with about 1k rows that I want to display. This task obviously chokes the UI thread, resulting in a black screen while the onCreate() builds the table.
I've solved this by using AsyncTask which builds the wanted TableLayout in the "doInBackground" function and display it on the "onPostExecute" function.
Question #1:
Is there any better practice that I'm not familiar with?
Question #2:
My (simplified) "doInBackground" function looks like this:
protected Void doInBackground(Void... v) {
tmpTableLayout = populateTable("");
return null;
}
And my (simplified) "onPostExecute" function looks like this:
protected void onPostExecute(Void v) {
TableLayout ct = (TableLayout)findViewById(R.id.RealTable);
ct.removeAllViews();
/* WHATS HERE? */
}
What should I write instead of the "WHATS HERE?" in the last line of code in order to display the content of "tmpTableLayout" in "ct" ?
Thanks in advance!
Are you sure you want to display it all in one go?
One approach would be to dynamically load in more lines as the user scrolls down. So have a scroll listener that checks if the user is approaching the end of the content that is displayed and therefore start an AsyncTask or a thread loading more content.
Example:
Android List Activity with dynamically loaded images form the web in android
I would probably use a ListView and CursorAdapter and let Android manage fetching the data for you. See the accepted answer here.

Categories

Resources