Asked  6 Months ago    Answers:  5   Viewed   28 times

I want to make a pause between two lines of code, Let me explain a bit:

-> the user clicks a button (a card in fact) and I show it by changing the background of this button:

thisbutton.setBackgroundResource(R.drawable.icon);

-> after let's say 1 second, I need to go back to the previous state of the button by changing back its background:

thisbutton.setBackgroundResource(R.drawable.defaultcard);

-> I've tried to pause the thread between these two lines of code with:

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

However, this does not work. Maybe it's the process and not the Thread that I need to pause?

I've also tried (but it doesn't work):

new Reminder(5);

With this:

public class Reminder {

Timer timer;

        public Reminder(int seconds) {
            timer = new Timer();
            timer.schedule(new RemindTask(), seconds*1000);
        }

        class RemindTask extends TimerTask {
            public void run() {
                System.out.format("Time's up!%n");
                timer.cancel(); //Terminate the timer thread
            }
        }  
    }

How can I pause/sleep the thread or process?

 Answers

48

One solution to this problem is to use the Handler.postDelayed() method. Some Google training materials suggest the same solution.

@Override
public void onClick(View v) {
    my_button.setBackgroundResource(R.drawable.icon);

    Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() {
         @Override 
         public void run() { 
              my_button.setBackgroundResource(R.drawable.defaultcard); 
         } 
    }, 2000); 
}

However, some have pointed out that the solution above causes a memory leak because it uses a non-static inner and anonymous class which implicitly holds a reference to its outer class, the activity. This is a problem when the activity context is garbage collected.

A more complex solution that avoids the memory leak subclasses the Handler and Runnable with static inner classes inside the activity since static inner classes do not hold an implicit reference to their outer class:

private static class MyHandler extends Handler {}
private final MyHandler mHandler = new MyHandler();

public static class MyRunnable implements Runnable {
    private final WeakReference<Activity> mActivity;

    public MyRunnable(Activity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void run() {
        Activity activity = mActivity.get();
        if (activity != null) {
            Button btn = (Button) activity.findViewById(R.id.button);
            btn.setBackgroundResource(R.drawable.defaultcard);
        }
    }
}

private MyRunnable mRunnable = new MyRunnable(this);

public void onClick(View view) {
    my_button.setBackgroundResource(R.drawable.icon);

    // Execute the Runnable in 2 seconds
    mHandler.postDelayed(mRunnable, 2000);
}

Note that the Runnable uses a WeakReference to the Activity, which is necessary in a static class that needs access to the UI.

Tuesday, June 1, 2021
 
diegoiglesias
answered 6 Months ago
50

Use wait() and notifyAll() properly using a lock.

Sample code:

class YourRunnable implements Runnable {
    private Object mPauseLock;
    private boolean mPaused;
    private boolean mFinished;

    public YourRunnable() {
        mPauseLock = new Object();
        mPaused = false;
        mFinished = false;
    }

    public void run() {
        while (!mFinished) {
            // Do stuff.

            synchronized (mPauseLock) {
                while (mPaused) {
                    try {
                        mPauseLock.wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }

    /**
     * Call this on pause.
     */
    public void onPause() {
        synchronized (mPauseLock) {
            mPaused = true;
        }
    }

    /**
     * Call this on resume.
     */
    public void onResume() {
        synchronized (mPauseLock) {
            mPaused = false;
            mPauseLock.notifyAll();
        }
    }

}
Wednesday, June 2, 2021
 
MoarCodePlz
answered 6 Months ago
47

Hello you can use this code, it works for me in Android 2.3.3:

private String getAppName(int pID)
{
    String processName = "";
    ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
    List l = am.getRunningAppProcesses();
    Iterator i = l.iterator();
    PackageManager pm = this.getPackageManager();
    while(i.hasNext()) 
    {
          ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo)(i.next());
          try 
          { 
              if(info.pid == pID)
              {
                  CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));
                  //Log.d("Process", "Id: "+ info.pid +" ProcessName: "+ info.processName +"  Label: "+c.toString());
                  //processName = c.toString();
                  processName = info.processName;
              }
          }
          catch(Exception e) 
          {
                //Log.d("Process", "Error>> :"+ e.toString());
          }
   }
    return processName;
}
Wednesday, June 9, 2021
 
astaykov
answered 6 Months ago
57

Use the adapter's getSnapshots() method:

@Override
public void onBindViewHolder(MainActivity.DealsHolder holder, int position, DealsResponse model) {
    // ...
    holder.itemView.setOnClickListener(v -> {
        DocumentSnapshot snapshot = getSnapshots().getSnapshot(holder.getAdapterPosition());
        snapshot.getId();
        // ...
    }); 
}

The getId() method returns the document's id, so in collection/myDoc/someField, myDoc would be the id.

If you know your data structure in the next activity, you can recreate the reference with that id through the standard firestore.collection("foo").document("bar") methods. If you're looking for the general solution, I use getPath() a bunch:

fun Bundle.putRef(ref: DocumentReference) = putString(REF_KEY, ref.path)

fun Bundle.getRef() = FirebaseFirestore.getInstance().document(getString(REF_KEY))

If you want the id in your model, use a custom SnapshotParser:

val options = FirestoreRecyclerOptions.Builder<DealsResponse>()
        .setQuery(query) {
            it.toObject(DealsResponse::class.java).apply { id = it.id }
        }
        .build()
Thursday, August 19, 2021
 
jul
answered 4 Months ago
jul
74

I was wrong when I mentioned in the question that there is no process state information in the list of processes retrived using ActivityManager.

 ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
   List<RunningAppProcessInfo> list2= am.getRunningAppProcesses();
   for (RunningAppProcessInfo ti : list2) {

       Log.i("IMPORTANCE CODE",String.valueOf(ti.importance));
  }

ti.importance retrives a constant value which describes whether the process is running FOREGROUND, BACKGROUND, Empty of code etc...

More information can be found at the following location:

http://developer.android.com/reference/android/app/ActivityManager.RunningAppProcessInfo.html

Thanks, Navin

Thursday, August 19, 2021
 
Peter Thomas
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share