image Switcher is not working properly - android

i have an android application which should show Ads, those ads are pulled from server and then they are being saved on the phone,i made a method which should show ads but unfortunately,it's not working as expected it display the first image for a long time and then it loops over them too fast i have no idea why
here is my method
private void startShowAds(final ArrayList<Ad> adArrayList) {
Handler handler = new Handler();
for (int i = 0; i < adArrayList.size(); i++) {
Ad ad = adArrayList.get(i);
Runnable runnable = new Runnable() {
public void run() {
imageView.setBackgroundDrawable(getBitMap(ad.getFileUri()));
handler.postDelayed(this, ad.getDuration());
}
};
handler.postDelayed(runnable, ad.getDuration());
}
startShowAds(dbHelper.getAllAdRecords(longitude, latitude));
}
any help will be appreciated

Try this:
private void startShowAds(final ArrayList<Ad> adArrayList) {
Handler handler = new Handler();
long offset = 0;
for (int i = 0; i < adArrayList.size(); i++) {
Ad ad = adArrayList.get(i);
Runnable runnable = new Runnable() {
public void run() {
imageView.setBackgroundDrawable(getBitMap(ad.getFileUri()));;
}
};
handler.postDelayed(runnable, offset);
offset += ad.getDuration();
}
}

Related

Android handler not repeating

I'm trying to use "handler" to repeat a function (really trying to learn how to use it), but the function is only executed once.
public Runnable runnableCode = new Runnable() {
#Override
public void run() {
if (changeColor) {
myPaint.setColor(Color.BLUE);
Rect r = new Rect(0, 0, widthInPixels * 90, heightInPixels * 90);
myCanvas.drawRect(r, myPaint);
changeColor = false;
} else {
myPaint.setColor(Color.RED);
Rect r = new Rect(0, 0, widthInPixels * 90, heightInPixels * 90);
myCanvas.drawRect(r, myPaint);
changeColor = true;
}
handler.postDelayed(runnableCode, 1000);
}
};
public void play (View view) {
handler.post(runnableCode);
}
You should loop through your handler to repeat itself. But you are just calling it once.
Try this code below:
final Handler handler = new Handler();
int count = 0; //keep track of count
final Runnable runnable = new Runnable() {
public void run() {
if (count++ < 5) { //how many times do you want to repeat?
handler.postDelayed(this, 5000); //repeat handler
}
}
};
//initial trigger
handler.post(runnable);
Let me know if you have any questions. Thanks.
Ensure that your bool changeColor is being modified by making it a final one element array
Try code below:
final Handler handler = new Handler();
final boolean[] changeColor = {false};
Runnable runnableCode = new Runnable() {
#Override
public void run() {
if (changeColor[0]) {
// code here
changeColor[0] = false;
} else {
// other code here
changeColor[0] = true;
}
messageHandler.postDelayed(this, 1000);
}
};
handler.post(runnableCode);
I tried adding a "toast", and that does get repeated; the problem's the drawing for some reason.
I tried firing the function from a button, and it looks like the repetitions accumulate and then fire all at once when I hit the button again.
Still fighting with this. I've also tried a timer, thread.sleep and ScheduledThreadPoolExecutor, and nothing.

Android: Playing MIDI Notes Using Handler and Scrolling RecyclerView Accordingly

I am playing MIDI notes using this library as follows:
handler.postDelayed(new Runnable() {
ShortMessage message;
#Override
public void run() {
{
MidiEvent event = midiEvents.get(index[0]);
if (index[0] < midiEvents.size() - 1) {
delta = midiEvents.get(index[0] + 1).getDelta();
time[0] = timeFactor * midiEvents.get(index[0] + 1).getDelta();
mTotalMidiTime += time[0];
int noteValue;
int NOTE_STATUS;
if (event instanceof NoteOn) {
noteValue = ((NoteOn) event).getNoteValue();
NOTE_STATUS = NOTE_ON;
if (index[0] != 0) {
if (delta != 0) {
Intent intent = new Intent();
intent.setAction(Constants.SCROLL_RECYCLERVIEW);
localBroadcastManager.sendBroadcast(intent);
}
}
} else {
noteValue = ((NoteOff) event).getNoteValue();
NOTE_STATUS = NOTE_OFF;
}
try {
message = new ShortMessage(NOTE_STATUS, 2, noteValue,
127);
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent();
intent.setAction(Constants.ACTION_SEEK);
localBroadcastManager.sendBroadcast(intent);
if (message != null)
recv.send(message, -1);
index[0]++;
} else {
index[0] = 0;
time[0] = 1;
mTotalMidiTime = mMinimumTime;
delta = 0;
}
handler.postDelayed(this, time[0]);
}
}
}, 0);
With each NoteOn event I am smooth scrolling a RecyclerView and updating a Seekbar using a LocalBroadcastManager
My problem is that playback is fine when UI operations are not performed but playback and UI get completely out of sync as soon as multiple MIDI notes (chords) are played in very quick succession. It would be appreciated if any performance improvements are suggested for the same. I have already tried performing the UI operations in runOnUiThread and also launching a new Handler for UI operations.
My BroadcastReceiver is as follows:
BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String actionType = intent.getAction();
switch (actionType) {
case Constants.SCROLL_RECYCLERVIEW:
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
mNotesRecycler.smoothScrollBy(pixels, 0);
}
});
break;
case Constants.ACTION_SEEK:
Handler seekHandler = new Handler();
seekHandler.post(new Runnable() {
#Override
public void run() {
mPinchSeekBar.setSelectedCentreValue(mTotalMidiTime);
mCurrentTime.setText(timeInMinutes((int) mTotalMidiTime));
}
});
break;
}
}
};
Besides the optimizations you can do, I think the problem itself is RecyclerView's smoothScroll is more a method you call sometimes to do a fancy scroll rather than bomb it with requests that cause it to constantly recompute the running animation.
One thing you can try is to write yourself a simple scroll handler that calls mRecyclerView.scrollTo() that does the scroll without animation but I guess it's going to be more reliable.
Try something like this
Handler mHandler = new Handler();
int mPosition, mTargetPosition;
#IntRange(from = 20, to = 100)
final int INTERVAL = 50; // try with 50 ms or a little lower
Runnable mTimerScroll = new Runnable() {
public void run() {
if (mPosition != mTargetPosition) {
if (mPosition < mTargetPosition) {
mPosition += mDelta;
if (mPosition > mTargetPosition) mPosition = mTargetPosition;
}
if (mPosition > mTargetPosition) {
mPosition -= mDelta;
if (mPosition < mTargetPosition) mPosition = mTargetPosition;
}
mRecyclerView.scrollTo(mPosition, 0);
}
// repeat every 50ms
mTimerScroll.post(mRunnable, INTERVAL);
}
}
And then you start it
void startTimer() {
stop(); // prevent double start
mHandler.post(mTimerScroll);
}
void stopTimer() {
mHandler.removeCallbacks(mTimerScroll);
}
void scroll(int target) {
mTargetPosition = target;
}
void scrollBy(int pixels) {
scroll(mPosition + pixels);
}
I don't know the specifics of your app but it might work.
About optimization, you are using a lot of stuff there that can or cannot be necessary depending on the specifics of your library, etc, but if there are no different threads or services involved you could avoid the LocalBroadcast thing and all the handler.post() as everything is already on the UI thread (handler.post just posts a runnable to the thread where the handler was created, that in your case is the UI thread, so it doesn't do anything)

How to resolve ANR while invoking a list

I am developing an app in which a thread will run in main thread and it will call a list of users in every 1 sec,but i am getting the pop up that ANR. please suggest. How To Resolve?
Below is my code
super.onCreate(savedInstanceState);
System.setProperty("java.net.preferIPv4Stack", "true");
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
mHandler = new Handler();
Runnable runable = new Runnable() {
#Override
public void run() {
try{
listofUsers = GcmIntentService.getListOfUsers();
if (listofUsers.size() > 0) {
for (int index = 0; index < listofUsers.size(); index++) {
if (index == 0) {
startTime = listofUsers.get(0).getLoggedinDateTime();
} else {
Calendar calender1 = Calendar.getInstance();
calender1.setTime(startTime);
calender1.add(Calendar.SECOND, i);
newTime = calender1.getTime();
listofUsers.get(index).setLoggedinDateTime(newTime);
i = i + 72;
}
///user time is checked with the current system time.
Iterator<UserInformation> userDetailsIter = listofUsers.iterator();
Calendar calender2 = Calendar.getInstance();
while (userDetailsIter.hasNext()) {
UserInformation newUserInfo = userDetailsIter.next();
Date userTime=newUserInfo.getLoggedinDateTime();
Date systemTime=calender2.getTime();
if ( userTime.compareTo(systemTime) < 0 ) {
userDetailsIter.remove();
}
}
}
}
mHandler.postDelayed(this, 1000);
}
catch (Exception e) {
// TODO: handle exception
}
finally{
//also call the same runnable
mHandler.postDelayed(this, 100);
}
}
};
mHandler.postDelayed(runable, 100);
}
Please help me by guiding me about what I have done wrong
You can't make a while loop or any kind of long running operation on main queue
why don't you make a normal thread inside a repeated timer
like the below code
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
check();
}
}, 0, 100);
and inside check make a thread and do what ever you want
public void check(){
new Thread(new new Runnable() {
#Override
public void run() {
// do what you want here
}
}).start();
}

Why doesn't this update the screen after it is fired?

I am scheduling a simple task that should update a text field in 4 seconds.
However everytime this is called the activity pauses and does not show the value in the text field until I restart the activity.
private void showDelayedValue() {
Runnable longRunningTask = new Runnable() {
public void run() {
int randomVal = randomNumberGenerator.nextInt(30 - -10) - 10; //random number between -10 and 30
String randomValStr = Integer.toString(randomVal);
Log.i(this.getClass().getSimpleName(),
"FIRED startScheduler: " + randomValStr);
theFieldOnScreenTV.setText(randomTempStr);
}
};
//show the value in 2 seconds
scheduledTaskExecutor.schedule(longRunningTask, 4, TimeUnit.SECONDS);
}
The log shows:
FIRED startScheduler: 4
but does not update the TextView theFieldOnScreenTV
Instead onPause is called right after Fired startScheduler: is displayed in LogCat.
Many thanks!
EDIT:
This worked for me following Alex' approach:
private void showDelayedValue() {
int randomX = randomNumberGenerator.nextInt(30 - -10) - 10;
final String randomXStr = Integer.toString(randomX);
final Runnable updateFieldR = new Runnable() {
public void run() {
theFieldOnScreenTV.setText(randomXStr);
}
};
Runnable longRunningTask = new Runnable() {
public void run() {
theFieldOnScreenTV.post(updateFieldR);
}
};
scheduledTaskExecutor.schedule(longRunningTask, 4, TimeUnit.SECONDS);
}
instead of
theFieldOnScreenTV.setText(randomTempStr);
try
theFieldOnScreenTV.post(new Runnable() { theFieldOnScreenTV.setText(randomTempStr); } );
Have a try using Handlers.
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
theFieldOnScreenTV.setText(randomTempStr);
}
});

Android: Time delay in a loop with updating UI

What I'm trying to create is a simple progress bar, that would load for ~10 sec.
So what I want is a for loop like this:
for(int i = 1; i <= 100; i++) {
progressDialog.setProgress(i);
//100ms delay
}
Thanks
You can use Async Task for the purpose
in preExecute() method initialize loop index to 0;
in background process sleep thread for 10 seconds, and then call sendUpdate method to send progress
in postExecute update progress bar to progress get in parameter.
The following code may be helpful for you.
public void startProgress(View view) {
// Do something long
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
progressDialog.setProgress(value);
}
});
}
}
};
new Thread(runnable).start();
}
A shorter solution without explicitly creating a new Thread would look like this:
final Handler handler = new Handler(Looper.getMainLooper());
final int sleepMs = 100;
for (int i = 1; i <= 100; ++i) {
handler.postDelayed(() -> progressDialog.setProgress(value), i * sleepMs);
}

Categories

Resources