Realm access from incorrect thread Android - java

I am dealing with this issue on Android :
Realm access from incorrect thread. Realm objects can only be accessed on the thread they where created.
I want to use Realm in my RemoteViewsFactory with
public class RemoteViewsX implements RemoteViewsFactory {
public RemoteViews getViewAt(int paramInt) {
if (this.results != null && this.results.size() != 0 && this.results.get(paramInt) != null) {
//FAILED HERE
}
}
...
This call failed! Why ?
I fetch my data like this in my class:
public void onDataSetChanged() {
Realm realm = Realm.getInstance(RemoteViewsX.this.ctx);
this.results = realm.where(Model.class).findAll();
}
I called my remoteFactory like this :
public class ScrollWidgetService extends RemoteViewsService {
#Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new RemoteViewsX (getApplicationContext());
}
}
Any idea ?

If the problem is caused by calling onDataSetChanged and getViewAt from another thread, you can force them to use the same thread, creating your own HandlerThread like this:
public class Lock {
private boolean isLocked;
public synchronized void lock() throws InterruptedException {
isLocked = true;
while (isLocked) {
wait();
}
}
public synchronized void unlock() {
isLocked = false;
notify();
}
}
public class MyHandlerThread extends HandlerThread {
private Handler mHandler;
public MyHandlerThread() {
super("MY_HANDLER_THREAD");
start();
mHandler = new Handler(getLooper());
}
public Handler getHandler() {
return mHandler;
}
}
public class RemoteViewsX implements RemoteViewsFactory {
private MyHandlerThread mHandlerThread;
...
}
public void onDataSetChanged() {
Lock lock = new Lock();
mHandlerThread.getHandler().post(new Runnable() {
#Override
public void run() {
Realm realm = Realm.getInstance(ctx);
results = realm.where(Model.class).findAll();
lock.unlock();
}
});
lock.lock();
}
public RemoteViews getViewAt(int paramInt) {
Lock lock = new Lock();
final RemoteViews[] result = {null};
mHandlerThread.getHandler().post(new Runnable() {
#Override
public void run() {
// You can safely access results here.
result[0] = new RemoteViews();
lock.unlock();
}
});
lock.lock();
return result[0];
}
I copied Lock class from this page: http://tutorials.jenkov.com/java-concurrency/locks.html
Do not forget to quit the handler thread when your tasks are done.

I am based on RxJava, so I do this in a realm. I clone each item because they are part of the main thread and that messes up when I am working in another thread such a widget home screen.
myRealm.where( Dog.class ).findAllAsync().subscribe( mainThreadDogs->{
thisThreadDogs.clear();
for( Dog dog: mainThreadDogs ){
thisThreadDogs.add( ModelUtil.cloneDog( dog ) );
}
});

Related

Android MIDI Threading InteruptedException - Aftertouch Messages

Trying to run MIDI on my Android app. I'm following the midisuite example to configure my app and it works fine with the exception of aftertouch. Whenever I try to trigger aftertouch, I run into a threading exception type
InteruptedException. How should I prevent this threading issue? My knowledge on multithreading isn't the best or else I would've figured this out already. All I can really tell right now is that the message is sending too fast and the thread hasn't woken up yet from its sleep call.
I followed the github repo with my code as follows:
MidiReceiver subclass:
#TargetApi(Build.VERSION_CODES.M)
public class MidiEngine extends MidiReceiver {
public AudioActivity activity;
private MidiEventScheduler eventScheduler;
private MidiFramer midiFramer;
private MidiReceiver midiReceiver = new MyReceiver();
private Thread mThread;
private boolean go;
private int mProgram;
public MidiEngine() {
this(new AudioActivity());
}
public MidiEngine(AudioActivity activity) {
this.activity = activity;
midiReceiver = new MyReceiver();
midiFramer = new MidiFramer(midiReceiver);
}
public AudioActivity getActivity() {
return this.activity;
}
/* This will be called when MIDI data arrives. */
#Override
public void onSend(byte[] data, int offset, int count, long timestamp)
throws IOException {
if (eventScheduler != null) {
if (!MidiConstants.isAllActiveSensing(data, offset, count)) {
eventScheduler.getReceiver().send(data, offset, count,
timestamp);
}
}
}
// Custom Listener to send to correct methods
private class MyReceiver extends MidiReceiver {
#Override
public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
byte command = (byte)(msg[0] & MidiConstants.STATUS_COMMAND_MASK);
int channel = (byte)(msg[0] & MidiConstants.STATUS_CHANNEL_MASK);
switch (command) {
case MidiConstants.STATUS_NOTE_ON:
activity.keyDown(i, msg[1], msg[2]);
break;
case MidiConstants.STATUS_NOTE_OFF:
activity.keyUp(channel, msg[1]);
break;
case MidiConstants.STATUS_POLYPHONIC_AFTERTOUCH:
activity.keyDown(channel, msg[1], msg[2]);
break;
case MidiConstants.STATUS_PITCH_BEND:
activity.pitchBendAction(channel, (msg[2] << 7) + msg[1]);
break;
case MidiConstants.STATUS_CONTROL_CHANGE:
activity.ccAction(channel, msg[1], msg[2]);
break;
case MidiConstants.STATUS_PROGRAM_CHANGE:
mProgram = msg[1];
break;
default:
break;
}
}
}
class MyRunnable implements Runnable {
#Override
public void run() {
do {
try {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
processMidiEvents();
}
catch (Exception e) {
Log.e("Java", "SynthEngine background thread exception.", e);
}
}
});
Thread.sleep(100);
}
catch (InterruptedException e) {
Log.e("Java", "Threading exception", e);
}
}
while (go);
}
}
/**
* #throws IOException
*
*/
private void processMidiEvents() throws IOException {
long now = System.nanoTime();
MidiEventScheduler.MidiEvent event = (MidiEventScheduler.MidiEvent) eventScheduler.getNextEvent(now);
while (event != null) {
midiFramer.send(event.data, 0, event.count, event.getTimestamp());
eventScheduler.addEventToPool(event);
event = (MidiEventScheduler.MidiEvent) eventScheduler.getNextEvent(now);
}
}
public void start() {
stop();
go = true;
mThread = new Thread(new MyRunnable());
mThread.setPriority(6);
eventScheduler = new MidiEventScheduler();
mThread.start();
}
public void stop() {
go = false;
if (mThread != null) {
try {
mThread.interrupt();
mThread.join(500);
}
catch (Exception e) {
}
mThread = null;
eventScheduler = null;
}
}
}
Stack Trace Error (line 154 refers to the Thread.sleep part in my custom Runnable class):
Java: Threading exception
java.lang.InterruptedException
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1031)
at java.lang.Thread.sleep(Thread.java:985)
at com.rfoo.midiapp.communication.MidiEngineInput$MyRunnable.run(MidiEngineInput.java:154)
at java.lang.Thread.run(Thread.java:818)
Thanks!
EDIT: Thread start
Midi Device Service subclass (thread will start whenever a device has connected or disconnected).
#TargetApi(Build.VERSION_CODES.M)
public class MidiSynthDeviceService extends MidiDeviceService {
private static final String TAG = "MidiSynthDeviceService";
private boolean midiStarted = false;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
AudioActivity.midiEngine.stop();
super.onDestroy();
}
#Override
// Declare the receivers associated with your input ports.
public MidiReceiver[] onGetInputPortReceivers() {
return new MidiReceiver[] { AudioActivity.midiEngine };
}
/**
* This will get called when clients connect or disconnect.
* You can use it to turn on your synth only when needed.
*/
#Override
public void onDeviceStatusChanged(MidiDeviceStatus status) {
if (status.isInputPortOpen(0) && !midiStarted) {
AudioActivity.midiEngine.start();
midiStarted = true;
} else if (!status.isInputPortOpen(0) && midiStarted){
AudioActivity.midiEngine.stop();
midiStarted = false;
}
}
}
Activity class:
public class AudioActivity extends AppCompatActivity {
private Thread thread;
public static MidiEngine midiEngine;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Layout inits
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Setup MIDI:
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI)) {
Toast.makeText(this, "MIDI not supported!", Toast.LENGTH_LONG).show();
}
else {
midiEngine = new MidiEngine(this);
setupMidi();
}
// Setup audio thread:
if (thread == null) {
thread = new Thread() {
public void run() {
setPriority(Thread.MAX_PRIORITY);
// Runs an Open SL audio thread (C++)
// This generates a waveform.
// AudioEngine is a wrapper class connecting C++ to Java
AudioEngine.runProcess();
}
}
}
}
public void setupMidi() {
if (activity == null) activity = (AudioActivity) getContext();
mMidiManager = (MidiManager) activity.getSystemService(AudioActivity.MIDI_SERVICE);
if (mMidiManager == null) {
Toast.makeText(activity, "MidiManager is null!", Toast.LENGTH_LONG).show();
return;
}
// Get Device Info
MidiDeviceInfo deviceInfo = MidiTools.findDevice(mMidiManager, "RFOO", "AudioApp");
// MIDI Input
portIndex = 0;
inputPortSelector = new MidiOutputPortConnectionSelector(mMidiManager, activity, R.id
.inputListView, deviceInfo, portIndex);
inputPortSelector.setConnectedListener(new MyPortsConnectedListener());
midi_ch_input = 0;
midi_ch_output = 0;
}
// Bunch of UI code here....
}

Reuse code that performs async code and posts back to the UI thread

I have a class with 6 async methods, each one should call a blocking method. (meaning, a blocking method is posted on a background thread, and the result is posted on the ui thread)
I find my self writing the following code 6 times (1 per each async method), having only the blocking method and 'result' object type different.
mBackgroundThreadHandler.post(new Runnable() {
#Override
public void run() {
final String result = myBlockingMethod();
mUIHandler.post(new Runnable() {
#Override
public void run() {
//use result on UI thread
}
});
}
});
mBackgroundThreadHandler - a handler for a background thread
mUIHandler - a handler for the ui thread
Is there a "pretty" way to reuse this code?
While still a bit lengthy, maybe this could help?
abstract class BgTask implements Runnable {
#Override
public void run() {
final String result = getResult();
mUIHandler.post(new Runnable() {
#Override
public void run() {
processResult(result);
}
});
}
abstract String getResult();
abstract void processResult(String result);
}
With the above class, the mBackgroundThreadHandler invocation becomes
mBackgroundThreadHandler.post(new BgTask() {
#Override
String getResult() {
return myBlockingMethod();
}
#Override
void processResult(String result) {
// UI magic.
}
});
you probably should look into doing custom handlers, instead of just posting Runnables to them
the UI custom handler
Handler mUIHandler = new Handler(Looper.getMainLooper()){
public void handleMessage (Message msg){
switch(msg.what){
case 0: // action 0,
doResultZero(msg.obj);
break;
case 1: // action 1
break;
case 2: // action 2
break;
}
}
};
the background handler
Handler mBackgroundThreadHandler = new Handler( /* insert here the background looper */){
public void handleMessage (Message msg){
switch(msg.what){
case 0: // action 0
msg.obj = executeActionZero();
mUIHandler.sendMessage(msg);
break;
case 1: // action 1
break;
case 2: // action 2
break;
}
}
};
so, to start the process you do:
Message m = new Message();
m.what = 0;
mBackgroundThreadHandler.sendMessage(m);
Use can use the following class
public class RunnableOnBackgroudAndResultOnUI {
private Handler mBackgroundThreadHandler;
private Handler mUIHandler;
public RunnableOnBackgroudAndResultOnUI(Handler backgroundThreadHandler, Handler uIHandler) {
mBackgroundThreadHandler = backgroundThreadHandler;
mUIHandler = uIHandler;
}
public void run(final Runnable background, final Runnable ui) {
mBackgroundThreadHandler.post(new Runnable() {
#Override
public void run() {
background.run();
mUIHandler.post(ui);
}
});
}
}
and execute it like this
RunnableOnBackgroudAndResultOnUI runnableOnBackgroudAndResultOnUI = new RunnableOnBackgroudAndResultOnUI(mBackgroundThreadHandler, mUIHandler);
runnableOnBackgroudAndResultOnUI.run(new Runnable() {
#Override
public void run() {
// run on background
}
}, new Runnable() {
#Override
public void run() {
// run on ui
}
});
}
});

Android - Sharing surfaceview between Activities or prevent drawing tasks to lock the main thread when switching activity

I am developing an app which uses a common header in all its activities.
The header contains a sort of a custom progress bar which indicates task completion. The "progress bar" is implemented by subclassing a SurfaceView and the drawing operations are managed by an inner ExecutorService.
The tasks which tell the "progress bar" to run a certain animation are issued by a Singleton custom AsyncTaskManager, which holds a reference to the custom SurfaceView and the current activity.
Some of the AsyncTasks the singleton manager controls are executed upon custom Activities onCreate method, hence sometimes the AsyncTaskManager notifies the progress bar to animate before the activity is actually displayed.
It can also happens that the user might choose to switch activity before the progressbar's drawing Runnable task is finished.
To better explain, this is what happens when I switch to some activities:
oldActivity tells the ExecutorService to cancel it's Future task that draws on the SurfaceView canvas.
newActivity's onCreate is triggered and issues the AsyncTaskManager
singleton to start a new AsyncTask.
The AsyncTask in its onPreExecute tells the progress bar to start drawing on its canvas.
The ExecutorService manages the drawing Runnable, which in turn
locks the SurfaceHolder
When the AsyncTask completes, in its onPostExecute method,
tells the surfaceview drawing Runnable to draw a different thing
according on the result.
The problem I am having is that SOMETIMES (not always - seems randomly but maybe it has to do with tasks threadpools), upon starting the new activity, the application skips frames xx where xx is apparently random (sometimes it skips ~30 frames, other times ~ 300, other times the app gets an ANR).
I have been trying to solve this for some days now, but to no avail.
I think the problem could be one of the following or a combination of both:
The drawing thread does not cancel/ends in a timely manner thus causing the SurfaceHolder to stay locked and thus preventing the Activity to take control of the View as it goes onPause/onResume and hence leading to the main thread skipping frames. The animation is by no means heavy in terms of computations (a couple of dots moving around) but it needs to last at least 300ms to properly notify the user.
The singleton AsyncTaskManager holds the reference to the "leaving activity"'s SurfaceView preventing the former to be destroyed until the surfaceholder is released and causing the frame-skipping.
I am more prone to believe the second issue is what is making Coreographer's angry and so this leads to the following question:
How can I share the SAME (as in the same instance) surfaceView (or any view, really) between all the activities or alternatively to allow the current instance of SurfaceView to be destroyed and recreated without waiting fot the threads to join/interrupt?
As it is now, the SurfaceView is being destroyed/recreated when switching between activities and I would have nothing against it if its drawing thread would stop as the new activity begins its lifecycle.
This is the custom AsyncTaskManager that holds a reference to the SurfaceView
public class AsyncTaskManager {
private RefreshLoaderView mLoader;
//reference to the customactivity holding the surfaceview
private CustomBaseActivity mActivity;
private final ConcurrentSkipListSet<RequestedTask> mRequestedTasks;
private volatile static AsyncTaskManager instance;
private AsyncTaskManager() {
mRequestedTasks = new ConcurrentSkipListSet<RequestedTask>(new RequestedTaskComparator());
}
public void setCurrentActivity(CustomBaseActivity activity) {
mActivity = activity;
if (mLoader != null) {
mLoader.onDestroy();
}
mLoader = (RefreshLoaderView) mActivity.getViewById(R.id.mainLoader);
}
This is what happens when an AsyncTask (RequestedTask in the above code snippet)
is executed
#Override
protected void onPreExecute() {
if (mLoader != null) {
mLoader.notifyTaskStarted();
}
}
#Override
protected Integer doInBackground(Void... params) {
//do the heavy lifting here...
}
#Override
protected void onPostExecute(Integer result) {
switch (result) {
case RESULT_SUCCESS:
if (mLoader != null) {
mLoader.notifyTaskSuccess();
}
break;
//TELLS THE SURFACE VIEW TO PLAY DIFFERENT ANIMATIONS ACCORDING TO RESULT ...
This is the CustomBaseActivity that holds the SurfaceView from which all others activities inherit.
public abstract class CustomBaseActivity extends FragmentActivity {
private volatile RefreshLoaderView mLoader;
//...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_base);
mLoaderContainer = (FrameLayout) findViewById(R.id.mainLoaderContainer);
mLoader = (RefreshLoaderView) findViewById(R.id.mainLoader);
//other uninteresting stuff goin on ...
And the code for the SurfaceView as well:
public class RefreshLoaderView extends SurfaceView implements SurfaceHolder.Callback {
private LoaderThread mLoaderThread;
private volatile SurfaceHolder mHolder;
private static final int ANIMATION_TIME = 600;
private final ExecutorService mExecutor;
private Future mExecutingTask;
public RefreshLoaderView(Context context) {
super(context);
...
init();
}
private void init() {
mLoaderThread = new LoaderThread();
...
}
#Override
public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2, int arg3) {
...
mHolder = this.getHolder();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
//uninteresting stuff here
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopThread();
}
private void stopThread() {
mLoaderThread.setRunning(false);
if (mExecutingTask != null) {
mExecutingTask.cancel(true);
}
}
private void startThread() {
if (mLoaderThread == null) {
mLoaderThread = new LoaderThread();
}
mLoaderThread.setRunning(true);
mExecutingTask = mExecutor.submit(mLoaderThread);
}
public void notifyTaskStarted() {
stopThread();
startThread();
mLoaderThread.setAction(LoaderThread.ANIMATION_TASK_STARTED);
}
public void notifyTaskFailed() {
mLoaderThread.setAction(LoaderThread.ANIMATION_TASK_FAILED);
}
public void notifyTaskSuccess() {
mLoaderThread.setAction(LoaderThread.ANIMATION_TASK_SUCCESS);
}
private class LoaderThread implements Runnable {
private volatile boolean mRunning = false;
private int mAction;
private long mStartTime;
private int mMode;
public final static int ANIMATION_TASK_STARTED = 0;
public final static int ANIMATION_TASK_FAILED = 1;
public final static int ANIMATION_TASK_SUCCESS = 2;
private final static int MODE_COMPLETING = 0;
private final static int MODE_ENDING = 1;
public LoaderThread() {
mMode = 0;
}
public synchronized boolean isRunning() {
return mRunning;
}
public synchronized void setRunning(boolean running) {
mRunning = running;
if (running) {
mStartTime = System.currentTimeMillis();
}
}
public void setAction(int action) {
mAction = action;
}
#Override
public void run() {
if (!mRunning) {
return;
}
while (mRunning) {
Canvas c = null;
try {
c = mHolder.lockCanvas();
synchronized (mHolder) {
//switcho quello che devo animare
if (c != null) {
switch (mAction) {
case ANIMATION_TASK_STARTED:
animationTaskStarted(c);
break;
case ANIMATION_TASK_FAILED:
animationTaskFailed(c, mMode);
break;
case ANIMATION_TASK_SUCCESS:
animationTaskSuccess(c, mMode);
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (c != null) {
mHolder.unlockCanvasAndPost(c);
}
}
}
}
private void animationTaskStarted(Canvas canvas) {
//do an animation here
}
private void animationCloseLoaderCycle(Canvas canvas) {
//do stuff here ...
} else {
mStartTime = System.currentTimeMillis();
mMode = MODE_ENDING;
}
}
private void queryThreadClose() {
mProgress = 0;
mMode = MODE_COMPLETING;
mRunning = false;
}
private void animationTaskFailed(Canvas canvas, int mode) {
switch (mode) {
case MODE_COMPLETING:
animationCloseLoaderCycle(canvas);
break;
case MODE_ENDING:
if (System.currentTimeMillis() - mStartTime < ANIMATION_TIME) {
//notify user task is failed
} else {
queryThreadClose();
}
break;
}
}
private void animationTaskSuccess(Canvas canvas, int mode) {
switch (mode) {
case MODE_COMPLETING:
animationCloseLoaderCycle(canvas);
break;
case MODE_ENDING:
if (System.currentTimeMillis() - mStartTime < ANIMATION_TIME) {
//notify user task is failed
} else {
queryThreadClose();
}
break;
}
}
}
public void onPause() {
stopThread();
}
public void onStop() {
stopThread();
}
public void onDestroy() {
stopThread();
}
}
Using DDMS when Coreographer warns me I'm skipping frame shows that there are usually around 30 threads (daemon and normal) running, where an asynctask, the main thread and the drawing task are waiting for something.
(Also, how can I check what are they waiting for?)
Thanks in advance for your help.
Edit: these are the main thread calls when it hangs, according to DDMS Threads view:
at hava.lang.Object.wait(Native Method)
at java.lang.Thread.parkFor(Thread.java:1205)
at sun.misc.Unsafe.park(Unsafe.java:325)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:813)
...
I solved this in the end. There was a mistake in the synchronized block:
while (mRunning) {
Canvas c = null;
try {
//mistake was here
c = mHolder.lockCanvas();
synchronized (mHolder) {
if (c != null) {
//do stuff
}
}
}
I was getting the canvas outside the synchronized block, thus causing a deadlock when the activity needed to be destroyed/recreated.
moving c = mHolder.lockCanvas(); inside the synchronized block solved this.
in the end the working code is as follows:
synchronized (mHolder) {
c = mHolder.lockCanvas();
if (c != null) {
switch (mAction) {
//do stuff
}
}
}
Thanks anyway!

Avoiding threads restarting when changing activity

Right now, when I change the activity, my thread seams to go to sleep or something. And when I come back to the main activity, there are two threads running, doing the same things. I'm not sure if this is the case, but it seems like it's something equal.
...
public class MainActivity extends Activity {
public static double cowCount = 195;
public static double income = 0.100;
static boolean twiceCow = false, Threadrunning = false;
...
public void inc() {
new Thread(new income()).start();
}
class income implements Runnable {
#Override
public void run() {
for (int i = 0; i < 20;) {
final int value = i;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
cowCount = cowCount + income;
refresh();
}
});
}
}
}
This is how my thread looks like.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
checkThread();
}
private void checkThread() {
if (Threadrunning == false)
inc();
Threadrunning = true;
}
public void inc() {
new Thread(new income()).start();
}
...
public void refresh () {
TextView myTextView = (TextView)findViewById(R.id.myText);
myTextView.setText("You Have " + String.valueOf((nf.format(cowCount)) + " Cows!"));
}
I don't really understand what I've done wrong.
Please review this post: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
Consider your activity re-start as the same thing as a config change.
This pattern, i.e. using a retained Fragment as a container for your thread, and proxying UI updates via callbacks to your activity, is a pattern that will work much better for you.
In your case you'd need only a single TaskCallback for your UI refresh(), e.g. onRefreshCowCount(int cows);

Is is possible to make a method execute only once?

I have a for loop and structure like this:
for(....)
....
....
if(isTrue)
... do something..
.. method to be executed once (doTrick) is declared outside for loop.
....endif
endfor
public void doTrick()
...
...
..end
Is it possible for a method in for loop to be executed only once?
Sure!..
if(!alreadyExecuted) {
doTrick();
alreadyExecuted = true;
}
Your can use AtomicBoolean to make sure the task is only called the first time:
import java.util.concurrent.atomic.AtomicBoolean;
public class Once {
private final AtomicBoolean done = new AtomicBoolean();
public void run(Runnable task) {
if (done.get()) return;
if (done.compareAndSet(false, true)) {
task.run();
}
}
}
Usage:
Once once = new Once();
once.run(new Runnable() {
#Override
public void run() {
foo();
}
});
// or java 8
once.run(() -> foo());
if you use kotlin, you can do this:
val execOnce by lazy {
print("hello, world")
}
In Java 8, you can effectively do this using automatic memoization as described here: Do it in Java 8: Automatic memoization
I'll admit that memoization could be considered overkill for a "run once" scenario, but it is a rather clean alternative to some described in previous answers.
For instance:
public void doSomething() { ... }
Map<Boolean, Boolean> cache = new ConcurrentHashMap<>();
public void doSomethingOnce() {
cache.computeIfAbsent(true, x -> {
doSomething();
return true;
});
}
You can avoid the if() by using this trick:
private Runnable once;
private final static Runnable NOP = new Runnable () {
public void run () {
// Do nothing
}
}
public void method () {
once = new Runnable () {
public void run () {
doTrick();
once = NOP;
}
}
for (...) {
...
once.run();
...
}
}
Another overkill solution:
Depending on what you want to do, it might be possible to use a static initialization block.
public class YourKlass{
public void yourMethod(){
DoTrick trick;
for( int i = 0; condition; i++){
// ... (1)
trick = new DoTrick(); // or any kind of accessing DoTrick
// ... (2)
}
}
}
public class DoTrick{
static{
// Whatever should be executed only once
}
}
Simple solution:
Or, instead you just want to execute the first part outside of the loop:
int i = 0;
if( condition ){
// ... (1)
// do trick
// ... (2)
}
for(i = 1; condition; i++){
// ... (1)
// ... (2)
}
perhaps the break keyword is what you need? After running you method call break; I am sorry its not 100% clear what you mean from your question.
Have a look here from the sun docs
my sample from my app:
boolean alreadyExecuted = false;
then :
private void startMyService() {
if(!alreadyExecuted) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 4 seconds
context.startService(new Intent(context, myService.class));
alreadyExecuted = true;
}
}, 4000);
}
I want to do something slight more complex. In a multi-threaded environment ensure that the methods is run only one (which is solved by Hover Ruan's answer above), but also block any thread so none return until the method is done.
My solution is to use a Semaphore to do the blocking.
public class Once implements Runnable {
private static Semaphore signal = new Semaphore(1,true);
private static boolean done=false;
#Override
public void run() {
if(done)
return;
signal.acquireUninterruptibly();
if(done) {
signal.release();
return;
}
doTrick(); // actually run the task
done=true;
signal.release();
return;
}
static int result; // Result of running the task
static int count; // number of times its been called
/**
* The task we only want to run once
*/
public void doTrick() {
++count;
Random rnd = new Random();
for(int i=0;i<10000;++i) {
result += rnd.nextInt(100);
}
try {
Thread.sleep(1000); // just to ensure all thread start
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i=0;i<5;++i) { // multiple instances
final Once task = new Once();
for(int j=0;j<5;++j) { // multiple calls of same instance
executor.submit(() -> {
task.run();
System.out.println("Result "+Once.result+" count "+Once.count);
} );
}
}
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The program should pause, waiting until the first thread has finished, then all other threads should finish printing the result stored from the first run.
or by using Shared Preferences:
sharedpref = PreferenceManager.getDefaultSharedPreferences(this);
isFirstRun = sharedpref.getBoolean("FIRSTRUN", true);
if (isFirstRun)
{
// Do your unique code magic here
SharedPreferences.Editor editor = wmbPreference.edit();
editor.putBoolean("FIRSTRUN", false);
editor.commit();
}else{
//this will repeat everytime
}
Here is an example way. Just use "new Getlineonce();"
class Getlineonce {
static int[] linesRun = new int[0];
public Getlineonce() {
boolean lineRan = false;
int line = Thread.currentThread().getStackTrace()[2].getLineNumber();
for(int i = 0; i < linesRun.length; i++) {
if(line == linesRun[i]) {
lineRan = true; //Dont print
}
}
if(!lineRan) {
add(line);
System.out.println(line + " ran!");
}
}
public void add(int line) {
int newSize = linesRun.length+1;
int[] linesRunBuff = new int[newSize];
for(int i = 0; i < newSize-1; i++) {
linesRunBuff[i] = linesRun[i];
}
linesRunBuff[newSize-1] = line;
linesRun = linesRunBuff;
}
}
For me, the perfect solution was...
public class MainActivity extends BaseActivity {
private static boolean splash = false;
if (!splash){
runSplash();
}
private void runSplash(){
MainActivity.splash = true;
}
}
Defined my variable as private static and use the access via class.variable in my function :)
Try this. First, this will be called only once when the app is being installed for the first time on the user's device. Use SharedPreferences this will help us to remember that this method has already been called so it will not re-call it again when the app is killed or even if the device was turned off. (But keep in mind that when the user un-stall and then re-install the app the method will be called again)
public class MainActivity extends AppCompatActivity {
private static boolean alreadyExecuted = false; // Use private static boolean
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); // Use SharedPreferences
if (!prefs.getBoolean("onlyonce", false)) {
startMyService(); // Method to be called only once as long as the app wont be un-stalled but there is
// no problem if the app will be killed or the device being turned off.
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("onlyonce", true);
editor.commit();
}
}
private void startMyService() {
if (!alreadyExecuted) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MainActivity.this, SecondActivity2.class);
startActivity(intent);
alreadyExecuted = true;
}
}, 4000);
}
}
}
import java.util.ArrayList;
class RemoveDuplicate {
public static void main(String[] args) {
ArrayList<String> originalList = new ArrayList<String>();
originalList.add("foo");
originalList.add("bar");
originalList.add("bat");
originalList.add("baz");
originalList.add("bar");
originalList.add("bar");
String str="bar";
ArrayList<String> duplicateList = new ArrayList<String>();
// adding duplicates to duplicateList
for(String currentString : originalList) {
if(currentString.startsWith(str)) {
duplicateList.add(currentString);
}
}
// removing duplicates in duplicatesList
for(String removeString : duplicateList) {
originalList.remove(removeString);
}
// finally adding duplicateElement
originalList.add(str);
for(String currEntry : originalList) {
System.out.println(currEntry);
}
}
}

Categories