Android: How to determine on which threads are my methods are running? - android

I would like to make sure that my methods are running on the threads that I supposed to be ran. For that, would like to add thread's name or id in my logs. In order to check if my methods are running in UIthread, thread1,thread2....threadx.
Problem:
guide me on what I need to set to have the thread's name or id. I am not sure of this, if you have better approach, please share to us on how to differentiate the UI threads to other additional running threads.
guide me on how to log the above mentioned name or id. I have already the logging system. Just want to know the method need to call to obtain the name or id. Maybe, thread.name() or thread.id().
Any guidance is appreciated.

Use ThreadLocal. Actually example in docs exactly what you need:
import java.util.concurrent.atomic.AtomicInteger;
public class UniqueThreadIdGenerator {
private static final AtomicInteger uniqueId = new AtomicInteger(0);
private static final ThreadLocal < Integer > uniqueNum =
new ThreadLocal < Integer > () {
#Override protected Integer initialValue() {
return uniqueId.getAndIncrement();
}
};
public static int getCurrentThreadId() {
return uniqueId.get();
}
} // UniqueThreadIdGenerator
If you want, you can pass desired name to Thread and set it to static ThreadLocal variable in the first line in run() method.

Related

OnSaveInstanceState/ RestCalls

I am relatively new to Android development, and I have a question about onSaveInstanceState(). I am currently working on a login Activity for an app. To check to see if the user can login to their account, I perform a rest call to a server and, based on the response-code, see if I should grant access to the user. The root of my question is based on the fact that I am trying to avoid passing the Activity's Context to my rest-call class. To do this, I create a boolean field in my login Activity representing whether or not the rest-call was successful and a runnable that updates said boolean that I pass to the rest-call class. I know this goes against the idea of an AsyncTask, but I can't find any alternative to simply putting up a dialog box telling the user to wait while this happens. My questions are below.
1) If I use savedInstanceState() in the onCreate method, how do I instantiate this boolean field for the first time barring null checking an Object boolean? What I mean by this is that after the Activity is destroyed for whatever reason (such as orientation change, etc...) I will use the boolean value stored in my overriden onSaveInstanceState method; however, when it is created for the first time, it has no reference to a boolean value so it has to create one.
2) Does this Runnable even help? I did it so that I wouldn't have to pass the context, but if the Activity is going to be deleted before the RestCall(AsyncTask) is complete, does it really matter whether you pass the context or a Runnable affecting a field of the Activity? The more I think about this, the more I believe it is not going to make much of a difference as it will still result in it pointing to a non-existent object. I am trying to avoid using a Singleton design as I have gathered it is not optimal, but because of the potential lag in time with an AsyncTask, I am beginning to think that it may not be avoidable.
I know onSaveInstanceState() is a topic that has been brought up a lot on StackOverflow, however, I could not find an answer to these questions. I apologize if there has already been a thread for this, but any help or guidance on this would be greatly appreciated! Thank You!
Login Activities' setup:
public class LoginActivity extends Activity implements View.OnClickListener {
private EditText username_et;
private EditText password_et;
private Button login_b;
private boolean login_success = true;
private Runnable run;
/**
* Instances created when app starts
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_login);
// login_success = false;
login_success = savedInstanceState.getBoolean("login_success");
username_et = (EditText) findViewById(R.id.username_text);
username_et.setOnClickListener(LoginActivity.this);
password_et = (EditText) findViewById(R.id.password_text);
password_et.setOnClickListener(LoginActivity.this);
login_b = (Button) findViewById(R.id.login_button);
login_b.setOnClickListener(LoginActivity.this);
run = new Runnable() {
#Override
public void run() {
login_success = true;
}
};
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putBoolean("login_success", login_success);
}
Congratulations. You just discovered Android's dirty little secret.
AsyncTask has an inherent design flaw. It doesn't deal well with configuration changes that happen during background task execution because of exactly the problem you mentioned. It needs to hold a reference to the activity, but there's no guarantee that the reference will still be valid by the time the background task completes.
Here are two ways to overcome this problem:
I refer you to Alex Lockwood's excellent blog post on using hidden fragments with setRetainInstance(true) to span activity destruction and recreation. This is a more involved solution than the next one, but this solution has the advantage that you can still report progress with callbacks. If you were intending to call publishProgress() in your AsyncTask, then this is the method you should use.
Use a Loader. Loaders were designed around database data retrieval in the background, but the fact is that they can also be used to handle remote server access in the background as well. I use a Loader for the majority of my remote server tasks.
Here's an example:
public static class ResetPasswordLoader extends AsyncTaskLoader<Pair<CharSequence, Exception>> {
private static final String TAG = "ResetPasswordLoader ";
private String mEmail;
public ResetPasswordLoader(Context context, String email) {
super(context);
mEmail = email;
// set the content-changed flag
onContentChanged();
}
#Override
protected void onStartLoading() {
// only start the load if the content-changed flag is set
// takeContentChanged() returns the value of the flag before it is cleared
if (takeContentChanged()) {
forceLoad();
}
}
#Override
public Pair<CharSequence, Exception> loadInBackground() {
CharSequence result = null;
Exception exc = null;
try {
result = Service.getInstance().resetPassword(mEmail);
} catch (RemoteServiceException e) {
exc = e;
Log.e(TAG, "loadInBackground(), email = " + mEmail, e);
}
return new Pair<>(result, exc);
}
}
Also, in my onLoadFinished() override I make sure to call loaderManager.destroyLoader() on the loader's id.
Again, Alex Lockwood's blog has some great articles on loaders as well.
For the UI, something I do frequently is put up a indeterminate progress bar over the UI upon calling loaderManager.initLoader(). I also set a boolean like mProgressShown. This boolean gets saved in onSaveInstanceState, so when the activity/fragment is created again, I restore the boolean value which tells me to show the progress bar immediately. Some time later onLoadFinished will be called and I clear mProgressShown and hide the progress bar.

HTTP helper class in a thread?

I am writing an app for android that connects to a server to get/post some xml data. I currently have a small class with static methods such as post(string URI, string body) and get() that wrap the httpclient calls to create a http post request and return the response. I am wondering if i should also have these method work in their own threads. Currently, i need to do a async task to call my Helper.post(..) method to connect to and get a request from a server. Is it better to just have the async stuff incorporated in the helper class to avoid having multiple repeated async tasks all across my app to just make post calls?
As a general principle it is best to wrap up repeated code so that you dont continually re-invent the wheel. Therefore if it is possible for you to wrap up the threading easily then it would be a good idea to do so.
This is not always very easy. Methods which get something from the network define want done with that data once it's been received. Usually you just return it. But if you're threading within the method then you have to push it somewhere. This leads to a lot of additional callbacks and you dont (in my experience) save much.
Rather than defining a bunch of static methods which do the threading for you, I would recommend you keep threading out of the static methods and define a bunch of abstract AsyncTasks instead. Each defines it's own doInBackground and leaves the onProgressUpdate and onPostExecute methods undefined. That way you get the best of both worlds - you re-use as much as possible (the doInBackground code) but are able to customize where the data is sent once received.
Example
Your static code:
public class MyStaticClass {
public static String getFoo( String name ) {
// use the network to get a string;
return "hello " + name; // Use your immagination.
}
}
An AsyncTask defined as public so that it can be re-used easily.
public class GetFooTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground( String... name ) {
return MyStaticClass.getFoo(name[0]);
}
}
Now to use it. Your static library or public async task could not have known what you need to do with the resulting string. So you tell it what to do with the result here:
public class MyActivity extends Activity {
#Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_view);
// You've already defined how to get the data
// so using it requires only minimal code now.
GetFooTask titleTask = new GetFooTask() {
#Override
public void onPostExecute( String heading ) {
((TextView) findViewById(R.id.heading)).setText(heading);
}
};
titleTask.execute("John");
}
}
In this example you can use the GetFooTask in as many activities as you like, just tell it where to put the data each time.
If you really think you will never want to do two network tasks on the same thread then you can combine the static code and the "abstract" AsyncTask. But more often than not I find I want to fire several things to and from the network before I finally return a result. If I did the threading in the network static code I would end up firing 10 threads for one request... therefore I keep threading out the static code.

Why use TAG in most of the Android logging code

I can see this is common practice among Android developers.
public final class TasksSample extends ListActivity {
private static final String TAG = "TasksSample";
private void method() {
Log.i(TAG, "message");
}
}
Will it be easier, if I do it this way? I need not to declare TAG for every new class.
public final class TasksSample extends ListActivity {
private void method() {
Log.i(getClass().getName(), "message");
}
}
Rather than writing getClass().getName() at each place where a log is placed in a particular activity, it is always preferred to have a TAG that would represent the name of the activity class.
Why use TAG?
When you are running your application there might be more than one Activity class in it. To distinguish which activity class has logged the information in logcat we use a TAG which of course represents the name of the class.
And the proper way (I am not saying what you have written is wrong) of writing the TAG is:
private static final String TAG = TasksSample.class.getSimpleName(); // and not "TasksSample"
Every previous answer is right, but I just wanna add a little comment.
private static final String TAG = TasksSample.class.getSimpleName();
or
private static final String TAG = "TasksSample"
The latter is used when you use proguard. As you know, proguard obfuscates class names and it affects logs too.
calling a function every time has it's toll and getClass().getName() is calling 2 functions every time you log something into the system (an already long process).
Therefor, it's better to save the tag is a final static String instead of calling the same function over and over again.
Yes its a common practice, and is supported by Google for logging & debugging. If you use getClass().getName() then you have to call getClass().getName() every time, so its a better approach use TAG.
Actually getClass().getName() returns the class name, where TAG represents easy understandable name/identification of your class.

Solution to access global data from everywhere - efficiently

I need to find a solution that holds and accesses large chunks of complex global data and methods. It has to be accessible from within activities and normal instance variables of various data classes.
This is how I have done it. I would just like to know if there is anything wrong with it or if there is a better/cleaner way.
First I extend Application like recommended many times...
public class MainDataManager extends Application{
public ... large chunks of data in arrays, lists, sets,....
//static variable for singleton access from within instance variables of other classes
public static MainDataManager mainDataManager;
//create and init the global data, and store it in the static variable of the class
#Override
public void onCreate() {
super.onCreate();
//in case it should get called more than once for any reason
if (mainDataManager == null) {
init();
mainDataManager = this;
}
}
Now accessing it from within activities like everywhere recommended...
MainDataManager mainDataManager = (MainDataManager)getApplicationContext();
And since I need to access it from normal instances of data classes ...
public class MyDataClass {
public MainDataManager mainDataManager;
public String name;
public MyDataClass(String namex) {
this.name = namex;
//this is why I defined the static variable within MainDataManager, so
//one has access to it from within the instance of MyDataClass
this.mainDataManager = MainDataManager.mainDataManager;
}
public void examplesForAccessing() {
//some examples on how to access the global data structure and associated methods
mainDataManager.someMethodAccess();
xyz = mainDataManager.someDataAccess;
mainDataManager.someIndirectMethodAccess.clear();
mainDataManager.someOtherData = false;
}
}
Since I have not done this so far, I would like to know if there is anything wrong with this. Memory, efficiency, ...
Thanks very much!
May I add a little sidenote?
I could also have just used a class MainDataClass and access by MainDataClass.var or MainDataClass.method(). Is there any REAL disadvantage?
Is the data in both cases held in heap/stack?
You haven't given much detail about your "large chunks of data" but keep in mind that the onCreate method is the first things that runs when your application is starting and it runs on the main/UI thread. This means that if you do long tasks in your init() method your UX will be poor, not to mention that you are risking an ANR exception.
The solution for that is simple:
Keep your onCreate short
Create a BG thread and use it to run all initialization code
Show a "Splash"/"Welcome" screen with the a proper progressbar while the BG thread is running.

Can I use an activity to initialize some objects then finish?

If I initialize some static objects in an activity and then call finish(), do those objects still exist elsewhere in the application? Like say I want to access them later on in a service.
If not, are there any other solutions where I could initialize some static objects one time that other classes will have access to?
Yes, doing that is possible. But for the static objects to continue to exist, there should be at least one Activity/Service in the application to be running. What I normally do for such variables is to create a class to hold static methods and variables. Something like this:
public class Utils
{
public static String s;
public static int i;
public static initStatics()
{
s = "";
i = 0;
}
}
This you can call from your other Activity/Service like this:
public class CustomService extends Service
{
#Override
public void onStart()
{
Utils.initStatics();
}
}
So, these variables will be available as long as your app is running. Hope that helped. Good luck!
For things of that nature you can use static member variables on the Application object. You will have to clean up manually (since onDestroy is never called), and you will need to make sure there is at least one Activity/Service in the application running to prevent the app's process from being destroyed by the OS.

Categories

Resources