How wait in a loop to execute a task? - android

for(int i=0; i < size; i++){
loadImageFromServer(i);
}
The loadImageFromServer(); takes sometime to load image from server .
Example:
when i is 0, loadImageFromServer(0) starts. But then loop executes again before completing the loadImageFromServer(0) and starts loadImageFromServer(1). Now I want the loop to wait for that time(I mean, first complete the task of loadImageFromServer(0)) and then execute the next loop. How to do that ?

As a suggestion, ideally you should download multiple images simultaneously, to do that use ThreadPoolExecutor.
int numberOfProcessor = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
numberOfProcessor * 2,
numberOfProcessor * 2,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>()
);
for (int i = 0; i < size; i++) {
executor.execute(new Runnable() {
#Override
public void run() {
loadImageFromServer();
}
});
}

Related

How to modify the code to have image slideshow in android?

I am trying to make a slideshow of a few images while making an android app. I am using this code below
final int[] array = {R.drawable.cow_1, R.drawable.cow_2, R.drawable.cow_3, R.drawable.cow_4};
for (int i = 0; i < 4; i++){
final int finalI = i;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
animal_image.setImageResource(array[finalI]);
}
}, 4000);
}
The problem I am facing is that I am not getting the slideshow of images one-by-one instead the code is showing the last image after the first one directly. There's some problem with the code, please help me fix it.
Try with below
final int[] array = {R.drawable.cow_1, R.drawable.cow_2, R.drawable.cow_3, R.drawable.cow_4};
for (int i = 0; i < 4; i++){
final int finalI = i;
Thread.sleep(4000);
animal_image.setImageResource(array[finalI]);
}
you have to add try{... }catch(Exception e){} block.
What you code is doing is that it is creating a Handler for each of the image and setting the delay to 4 seconds. The for loop will run instantly for each iteration and all the Handlers that have been created will run after 4 seconds. This causes the last image to show up because the last Handler will have run a few milliseconds after the rest. In order to fix this, you need to have an incremental timer for each Handler.
final int[] array = {R.drawable.cow_1, R.drawable.cow_2, R.drawable.cow_3, R.drawable.cow_4};
for (int i = 0; i < 4; i++){
final int finalI = i;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
animal_image.setImageResource(array[finalI]);
}
}, 4000 * finalI);
}
Using the above given code, the first image will be displayed, and all the other images will be displayed after a multiple of 4 seconds based on the image number (image 2 will be shown after 4 seconds, image 3 will be shown after 8 seconds, image 4 will be shown after 12 seconds and so on).

Android - Load more data using AsyncTask which gets data from API in RecyclerView

I'm trying to dynamically add items to my RecyclerView.
Basically, I am following Instagram style, especially in the search fragment of Instagram. Currently, my app gets the number of item sent by server (default is 10) and add it onto the number of displayed items on the recyclerview.
I have an interface to get the output from the server, here's the OnLoadMoreListener
System.out.println("OnLoadMore");
list.add(null);
profilTemanAdapter.notifyItemInserted(list.size());
handler.postDelayed(new Runnable() {
#Override
public void run() {
//remove progress item
list.remove(list.size() - 1);
profilTemanAdapter.notifyItemRemoved(list.size());
TimelineFriendListAPI timelineFriendListAPIInput = new TimelineFriendListAPI();
timelineFriendListAPIInput.kevin.query.user_id = userId;
timelineFriendListAPIInput.kevin.query.other_user_id = otherUserId;
timelineFriendListAPIInput.kevin.query.friend_mode = friendMode;
nextFriendList = result.kevin.results.friend_list;
TimelineFriendListAPIFunc timelineFriendListAPIFunc = new TimelineFriendListAPIFunc(BottomProfilTemanFragment.this.getActivity());
timelineFriendListAPIFunc.delegate = BottomProfilTemanFragment.this;
if (nextFriendList.size() == 10) {
counter += 10;
timelineFriendListAPIInput.kevin.query.friend_count = String.valueOf(counter);
Log.d("CounterBefore", String.valueOf(counter));
timelineFriendListAPIFunc.execute(timelineFriendListAPIInput);
Log.d("CounterAfter", String.valueOf(counter));
Log.d("FriendLists", nextFriendList.get(0).friend_alias);
//Refresh Per Item
for (int i = 0; i < 10; i++) {
list.add(nextFriendList.get(i));
profilTemanAdapter.notifyItemInserted(list.size());
Log.d("FriendLists", nextFriendList.get(i).friend_alias);
}
Log.d("FriendLists", nextFriendList.get(10).friend_alias);
Log.d("OnLoadNotifFriendSize10", "size = " + list.size());
profilTemanAdapter.setLoaded();
} else if (nextFriendList.size() < 10 && nextFriendList.size() > 0) {
int friendCounter = nextFriendList.size();
counter += friendCounter;
timelineFriendListAPIInput.kevin.query.friend_count = String.valueOf(counter);
timelineFriendListAPIFunc.execute(timelineFriendListAPIInput);
//Refresh Per Item
for (int i = 0; i < friendCounter; i++) {
list.add(nextFriendList.get(i));
}
profilTemanAdapter.notifyItemInserted(list.size());
profilTemanAdapter.setLoaded();
} else {
}
}
}, 1000);
System.out.println("loadMore");
Here's the Interface function in the same class
result = output; //result is a global variable to be accessed inside the OnLoadMore
//profilTemanAdapter = new ProfilTemanAdapter(list, recyclerView, output);
//createlist();
handler = new Handler();
list = output.kevin.results.friend_list;profilTemanAdapter = new `ProfilTemanAdapter(list, recyclerView, output);`
profilTemanAdapter.setOnLoadMoreListener(profilTemanAdapterHandler);
recyclerView.setAdapter(profilTemanAdapter);
Log.d("FriendLists", list.get(0).friend_alias);
As can be expected, nextFriendList.get(10).friend_alias which is the 11th value in the List, is still the same as nextFriendList.get(0).friend_alias as nextFriendList has not been updated through the interface.
How to display it correctly as in waiting for the AsyncTask to finish, but not using .get() so that it doesn't block UI thread just like Instagram (or any "InfiniteScrolling" app) ?
Small update :
Used ProgressBar in Async so that it loads the information gained from server before displaying, but it messed the layout. There's an EditText above the RecyclerView which gets repeated on every OnLoadMore. Moreover it doesn't look nice with ProgressBar popping up for every information load..
Another update :
I am able to display OnLoadMore items but it replaces the items before the new items.

how to add a large number of records in background to database in android

I need to insert bulk of data to database in my android application. I have a dialog box containing a listview which have rows name, date, frequency where frequency value would be anything like "Daily", "Monthly", "Quarterly", "Yearly". Here after adding rows to the listview I need to click the done button to save these data's to the database. I need to store each row based on its frequency value. That is, if the frequency value is "Daily" I need to store 1095 (i.e., 3*365-->daily records for 3 year) record to the database for that name, similarly for each frequency value ("Monthly"--> 3*12, "Quarterly"--> 3*4,...) so it cause a bulk insertion of rows to database and which results long time to executes so the user may feel bad and he can't do any other operations in the application without completing this.I am using ORMLite for adding data to database.I have done this as below.
for (int i = 0; i < listAdapter.getCount(); i++) {
Account rowAcct = new Account();
rowAcct = listAdapter.getItem(i);
if (rowAcct.getFreq().equals("Daily")) {
for (int y = 0; y < 1095; y++) {
Account nwEvt = new Account();
dueDt = saveController.getNextDay(dueDt);
nwEvt.setDueDate(dueDt);
evtId = saveController.createAcc(nwEvt);
}
} else if (rowAcct.getFreq().equals("Monthly")) {
for (int y = 0; y < 35; y++) {
Account nwEvt = new Account();
Date dueDt = saveController.getNextMonth(dueDt);
nwEvt.setDueDate(dueDt);
saveController.createAcc(nwEvt);
}
} else if (rowAcct.getFreq().equals("Quarterly")) {
for (int y = 0; y < 11; y++) {
Account nwEvt = new Account();
dueDt = saveController.getQuarterMonth(dueDt);
nwEvt.setDueDate(dueDt);
evtId = saveController.createAcc(nwEvt);
}
} else if (rowAcct.getFreq().equals("Half-Yearly")) {
for (int y = 0; y < 5; y++) {
Account nwEvt = new Account();
Date dueDt = saveController.getHalfYear(dueDt);
nwEvt.setDueDate(dueDt);
saveController.createAcc(nwEvt);
}
} else if (rowAcct.getFreq().equals("Yearly")) {
for (int y = 0; y < 2; y++) {
Account nwEvt = new Account();
Date dueDt = saveController.getNextYear(dueDt);
nwEvt.setDueDate(dueDt);
saveController.createAcc(nwEvt);
}
}
}
dialog.dismiss();
How can I minimise this insertion time or making this insertion process in background and make the user free to do other things in the application? Please suggest me the best way to perform this by making the user free.
first one you need to perform all work with DB in worker thread. Just use android build-in AsyncTasks
second check this, this answers to improve insert in db.
You need to use an IntentService class and its handler for this,which is designed for long running task.Request an IntentService class after clicking the done button and pass necessary data's with that intent like below
Intent intentEv= new Intent(Intent.ACTION_INSERT, null, getApplicationContext(), MyIntentService.class);
intentEv.putExtra("requestId", 101);
intentEv.putExtra("listAccounts",arrayList);
startService(intentEv);
This will request the Intentservice class and then you can perform the database insertion on background using the onHandleIntent(Intent intent) function in your IntentService.
public class MyIntentService extends IntentService{
public static final int STATUS_RUNNING = 0;
public static final int STATUS_FINISHED = 1;
public static final int STATUS_ERROR = 2;
public MyIntentService() {
super("BulkInsertionService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "Service Started!");
ArrayList<Account> listAccounts=(ArrayList<Account>) intent.getSerializableExtra("listAccounts");
/* perform the long running insert operations now.. */
this.stopSelf();
}
}
Also initialise your IntentService class in your AndroidManifest.xml file
Ok, use AsyncTaskLoader =) it check current Activity state =)

Calling Async task in a loop?

I want to call an Async task in a loop and execute it a few times in parallel.
I have a List of items which I split out into smaller lists with 10 items in each list.
Then for every small List I execute the Async task using THREAD_POOL_EXECUTOR.
Problem is, its not working. I'm thinking its because I use the same list each time when it is passed to the AsyncTask - and I think it may be passed as reference.
Do I need to somehow create new Lists dynamically?
//split the ListItems into 10s
if (actualThumbs.size() > 10){
List<List<ListItem>> parts = chopped(actualThumbs, 10); // this splits it into parts of 10
List< ListItem > listToSend = new ArrayList<ListItem>(); //this is the list to pass
for(int i = 0; i < parts.size(); i++){ //for every part
for(int x = 0; x < parts.get(i).size(); x++){ //for everything in that part
//add to its own List
listToSend.add(parts.get(i).get(x));
}
//this is the async task
loadActualThumbs thumbs = new loadActualThumbs();
//execute multiple threads
thumbs.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,listToSend );
listToSend.clear(); //clearing the list ready for a new one - PROBLEM?
}
}
else
{
//else just execute AsyncTask normally, this works OK
loadActualThumbs thumbs = new loadActualThumbs();
thumbs.execute(actualThumbs);
}
EDIT:
I tried changing my code, to instead add every List that I want to send to the Async task to another List, and then loop through that List of Lists and send each one:
if (actualThumbs.size() > 10){
List<List<ListItem>> parts = chopped(actualThumbs, 10);
List< ListItem > listToSend = new ArrayList<ListItem>();
List<List<ListItem>> sendMe = new ArrayList<List<ListItem>>();
for(int i = 0; i < parts.size(); i++){ //for every part
for(int x = 0; x < parts.get(i).size(); x++){ //for everything in that part
//add to its own ListItem?
listToSend.add(parts.get(i).get(x));
}
sendMe.add(listToSend);// add the List to this List
listToSend.clear();
}
for(int e = 0; e<sendMe.size();e++){ //loop through the list of lists
loadActualThumbs thumbs = new loadActualThumbs();
//execute multiple threads?
thumbs.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,sendMe.get(e) ); // execute async with correct List
}
}
else
{
if (actualThumbs.size() > 0){
//load actual thumbnails
loadActualThumbs thumbs = new loadActualThumbs();
thumbs.execute(actualThumbs);
}
}
Your code should look like this now :
List<List<ListItem>> parts = chopped(actualThumbs, 10);
for(List<ListItem> list : parts) {
new loadActualThumbs().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, list);
}
I am actually not sure what size the threadpool is or if it's a cached thread pool, but you can create your own threadpool with Executors.newCachedThreadPool() and Executors.newFixedThreadPool(int count)... but I'd just go with the AsyncTask.THREAD_POOL_EXECUTOR....should work :)
If you need to execute your asynctask for particular interval of time then you may make use of Timer for same ..
Like this ..
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
try {
System.out
.println("=================== I am in pooling state ===============");
GetBookingStatusAsyncTask performBackgroundTask = new GetBookingStatusAsyncTask();
performBackgroundTask.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Now when you need to kill this timer ..
timer.cancel();
timer = null;
Also make use of boolean check so as to avaoid infinite loop .. i.e if true then execute AsyncTask .. and if false then stop AsyncTask .. just like ..
public void callAsynchronousTask(boolean b) {
// timer.cancel();
if (b) {
System.out.println("============= Check for timer check " + tcheck);
// execute in every 10000 ms
tcheck++;
} else {
System.out
.println("============= Check for timer check + cancelling timer task "
+ tcheck);
timer.cancel();
timer = null;
System.out.println("=============timer is ===" + timer);
// finish();
return;
}
}
When you need to close this task then simply of true / false condition pass like ..you need to pass this in your AsyncTask.
callAsynchronousTask(true); / callAsynchronousTask(false);
Hope it helps!..

For Loop reading infinity

I am trying to make a simple screen that shows you the amount of money you have earned by the second, so im trying to create a live feed type textveiw that updates every second with the amount of money you have earned, with my code when it runs on my phone it only reads "infinity" and when i tried to add in a 1 second delay it froze all together, here is the code that i wrote, i am using a for loop because i didnt know of a better way if anyone has a better way of achieving what i am trying to do please let me know..
// Calculate pay per second
double PPS = (HW/3600);
double OTPPS = (OTW/3600);
double HPDPS = (HPD*3600);
double money = 0;
double Reserve = 0;
loc = 0;
// Display
for(int i=0; i<HPDPS & loc!=7; i++)
{
money = (PPS+Reserve);
Reserve = (Reserve+money);
TextView textView = (TextView) this.findViewById(R.id.yourpay);
textView.setText(String.valueOf(money));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Thanks in advance for any help!
======================================================================================
Here is an edited version but i am still having a problem where it just displays infinity on the screen, how do i fix this? or how do i use the timer method?
public void sendMessage(View view) {
// Receive messages from options page
Intent intent = getIntent();
double HW = intent.getDoubleExtra(Options.MESSAGE_HW, 0);
double OTW = intent.getDoubleExtra(Options.MESSAGE_OTW, 0);
double HPD = intent.getDoubleExtra(Options.MESSAGE_HPD, 0);
// Calculate pay per second
double PPS = (HW/3600);
double OTPPS = (OTW/3600);
double HPDPS = (HPD*3600);
double money = 0;
double Reserve = 0;
// Display
for(int i=0; i<HPDPS; i++)
{
money = (PPS+Reserve);
Reserve = (Reserve+money);
TextView textView = (TextView) this.findViewById(R.id.yourpay);
textView.setText(String.valueOf(money));
}
// set textView
}
Better way is to user a Timer and TimerTask.
EDIT:
Here is a sample application code to user Timer and TimerTask:
final TextView t1 = (TextView) findViewById(R.id.textView1);
final Timer t =new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
t1.setText("Hello" + counter++); //Place your text data here
//Place your stopping condition over here. Its important to have a stopping condition or it will go in an infinite loop.
if(counter == 10)
t.cancel();
}
});
}
}, 1000, 1000);
Hope this helps.
[1] You are doing Bitwise ANDing (Bitwise ANDing -> &) here
for(int i=0; i<HPDPS & loc!=7; i++)
^
[2] Your loc in always 0, because you did loc=0 and in for loop loc is never updated
So loc!=7 is ALWAYS TRUE

Categories

Resources