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).
Related
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();
}
});
}
I'm trying to create a random quiz app, but i'm facing a particular problem that i was not able to solve in the last 2 days.
I have all my questions and options inside of 2 different array of Strings. An int called flag which determines the progress of the quiz
int flag=0;
String allQuestions[]={"A","B","C","D","E","F","G","H","I","J"};
String allOptions[]={/*/Primeras opciones /*/"A","I","O",
/*/Segundas opciones/*/"E","O","I",
/*/Terceras opciones/*/"A","I","U",
/*/Cuartas opciones/*/"O","E","U",
*/Quintas opciones/*/"O","U","A",
/*/Sextas opciones/*/"I","U","E",
/*/Septimas opciones/*/"E","I","E"
/*/Octavas opciones/*/"A","I","U",
/*/Novenas opciones/*/"E","U","O",
/*/Decimas opciones/*/"A","O","U"};
This is how i pick the random numbers:
ArrayList<Integer> number = new ArrayList<Integer>();
for (int i = 1; i <= 10; ++i) number.add(i);
Collections.shuffle(number);
I have my buttons linked and make their text change once the quiz activity is created.
question=(TextView)findViewById(R.id.QuizCharacter);
answerA=(Button)findViewById(R.id.answerA);
answerB=(Button)findViewById(R.id.answerB);
answerC=(Button)findViewById(R.id.answerC);
answerD=(Button)findViewById(R.id.answerD);
answerE=(Button)findViewById(R.id.answerE);
answerF=(Button)findViewById(R.id.answerF);
question.setText(number.get(flag)); // <------ having problems here?
answerA.setText(allOptions[0]);
answerB.setText(allOptions[1]);
answerC.setText(allOptions[2]);
answerD.setText(allOptions[3]);
answerE.setText(allOptions[4]);
answerF.setText(allOptions[5]);
Now, the randomizer works, the problem is that if the created random number is the first question A, then the app crashes.
I tried changing what i assume is the problematic line for
question.setText(allQuestions[number.get(0)]);
And instead of having a chance to randomize, it crashes every time.
Why is it happening and how can i fix it?
EDIT:
onCreate method:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz1);
correct = 0;
flag=0;
ArrayList<Integer> number = new ArrayList<Integer>();
for (int i = 0; i < 10; ++i) number.add(i);
Collections.shuffle(number);
String questionCounter = "Question number (flag+1): " + (flag + 1);//+ "\nnumber.get(flag)="+ number.get(flag);
TextView questionNumber;
questionNumber = (TextView) findViewById(R.id.questionNumber);
questionNumber.setText(questionCounter);
question.setText(allQuestions[number.get(0)]);
answerA=(Button)findViewById(R.id.answerA);
answerB=(Button)findViewById(R.id.answerB);
answerC=(Button)findViewById(R.id.answerC);
answerD=(Button)findViewById(R.id.answerD);
answerE=(Button)findViewById(R.id.answerE);
answerF=(Button)findViewById(R.id.answerF);
question.setText(allQuestions[number.get(flag)]);
answerA.setText(allOptions[0]);
answerB.setText(allOptions[1]);
answerC.setText(allOptions[2]);
answerD.setText(allOptions[3]);
answerE.setText(allOptions[4]);
answerF.setText(allOptions[5]);
}
Edit 2:
Thanks to Shadab Ansari for the answer. I forgot to initialize the variable question.
You are not storing anything at 0th index of number.
for (int i = 1; i <= 10; ++i) number.add(i); //Runs from 1 to 10
Your loop should change to -
for (int i = 0; i < 10; ++i) number.add(i); //Runs from 0 to 9
Also, according to the logs, "question" may be null. So please initialize all the views before using it.
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.
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!..
I am having a problem working inside a handler call. The problem is something as follows:
Sprite sprite = new Sprite[spriteArrayLength];
IUpdateHandler mm[i] = new ........// you know what
for(int i = 0; i < spriteArrayLength; i++){
//many other actions
mm[i] = new IUpdateHandler() {
//do somthing with sprite array items
float anyVar = sprite[i].getX();//problem rises here
};
sprite[i].registerUpdateHandler(mm[i]);
}
Every time it shows an error saying i reaches out of array bound. That means the handler call executes after for loop ends and so i already crosses its limit. How can I do something like above in a proper way?
Edit:
Sorry for my previous mistake. The First line of the code will be:
Sprite sprite[] = new Sprite[spriteArrayLength];
IUpdateHandler mm[] = new ........// you know what
not this:
Sprite sprite = new Sprite[spriteArrayLength];
IUpdateHandler mm[i] = new ........// you know what
I just thought these line are not very important to mention that's why made the mistake. But still the problem remains same.
Edit-2:
I get "array out of bound" type run time error. Let's say, array size is 6. So, last element is 5. But inside UpdateHandler "i" begins with 6 and throws an error. And I tried making "i" final, even made it global by declaring as a class field. I am trying to write short code examples here because it contains many codes. Better version is as follows:
public int i;//global declaration
//inside some method:
Sprite sprite[] = new Sprite[spriteArrayLength];
IUpdateHandler mm[] = new IUpdateHandler[spriteArrayLength];
for(i = 0; i < spriteArrayLength; i++){
//many other actions
mm[i] = new IUpdateHandler() {
//do somthing with sprite array items
float anyVar = sprite[i].getX();//problem rises here
};
sprite[i].registerUpdateHandler(mm[i]);
}
Based on the code in your Edit-2, my suggestion is:
Sprite sprite[] = new Sprite[spriteArrayLength];
IUpdateHandler mm[] = new IUpdateHandler[spriteArrayLength];
for(i = 0; i < spriteArrayLength; i++){
//many other actions
mm[i] = new IUpdateHandler() {
private final int id = i; /* add this line */
// call Log.i() here is compiling error
#Override
public void onUpdate(float pSecondElapsed) {
//do somthing with sprite array items
/* And access id, instead of i in below code.
Here, I assume this statement is located
within onUpdate() or reset().
*/
float anyVar = sprite[id].getX();
}
#Override
public void reset() {
}
};
sprite[i].registerUpdateHandler(mm[i]);
}
You are using the index variable i in 2 different contexts.
In your code you do this before the loop using i as an array index:
IUpdateHandler mm[i] = new ........// you know what
then inside the loop, you are changing the value of i and referencing mm[i] and sprite[i].
I assume that you haven't correctly initialized the mm array to the correct size (spriteArrayLength)
The problem is that your update handler holds a reference to variable i but isn't evaluated until after the loop finishes. Instead of holding a reference to i, give it a reference to the specific sprite, and for readability make it final to avoid any doubt that it could change:
for(i = 0; i < spriteArrayLength; i++){
final Sprite currentSprite = sprite[i];
//many other actions
mm[i] = new IUpdateHandler() {
//do somthing with sprite array items
float anyVar = currentSprite.getX();
};
currentSprite.registerUpdateHandler(mm[i]);
}