How can I measure time that ListView/ListActivity takes for rendering its list?
I have a ListActivity that takes a long time to show (on older devices it's ~3s) and I'd like to optimize that.
EDIT:
I already have time between Activity1 and Activity2. During this time, Activity2 is doing some stuff (initializing). Among other things, it renders its list. I want to get time this activity takes to render that list. If total time between activities is 3s, I want to know whether rendering list takes 2.9s or 0.5s....
You could simply ouput the time. For example you could use the logcat
final long t0 = System.currentTimeMillis();
// code to measure
Log.w(TAG, "TEXT" + System.currentTimeMillis()-t0);
Of course you could use any other system for the ouput like a dialog or stuff. Just use what you like.
EDIT:
If you don't want to use a debug message in your code all the time you could do it like this:
Create a class called settings:
public class Settings {
public static final boolean DEBUG = true;
// If you prefer you could do use an enum
// enum debugLevel {SHOW_EVERYMESSAGE, ERRORS, IMPORTANT_MESSAGES, ...}
// In your classes you would have to check that DEBUG is less or equal than
// the debugLevel you want
}
In classes where you want to use a debug message simply do this
import xxx.yyy.Settings
class foo {
final static boolean DEBUG = Settings.DEBUG;
if(DEBUG){
// Debug messages
}
}
Now if you want to disable DEBUG messages you could simply set DEBUG = false in your Settings class.
If you want to measure between two activities you could use intents and send t0 with an intent to the other activity to compute the time. Of course you could include this with if(DEBUG){ /* code */ } statements to spare the sending of the intent in the final release. The if statements should not increase the computation of your code too dramatically.
I cannot tell if Java offers a better implementation using System.currentTimeMillis() or System.nanoTime(). Nevertheless, you should give the TimingLogger class a try. Take a look at this article describing the usage of the TimingLogger helper class.
Related
I know, there is a way to see which functions are called in log-cat is to write a log message on top for every function like this
#Override
protected void onDestroy() {
super.onDestroy();
Log.d("myTag","onDestroy function is called!");
// some logic
}
But it becomes irritating when you have more function.
So, I wonder if there is a way to see which functions are called in adb-logcat without writing log messages for every function.
I hope they can be fetched from somewhere in the stack but I couldn't find it.
You can try Hugo. In that case you have to annotate your methods with #DebugLog only. Then Hugo will generate logs for you (and will print out arguments and return value!). Example from GitHub:
#DebugLog
public String getName(String first, String last) {
SystemClock.sleep(15); // Don't ever really do this!
return first + " " + last;
}
And log output:
V/Example: ⇢ getName(first="Jake", last="Wharton")
V/Example: ⇠ getName [16ms] = "Jake Wharton"
Instead of printing log in every function. I (or most of the people) would suggest you to put debug.
To use debug first create breakpoints inside every function you want to check. To apply breakpoints simply left click in the area to the left of your code (refer image the pink circle represents a break-point).
Then to use Debug you have to press this button after successfully running your application.
As soon as the first method is called your application will pause at the break-point, then you can use F8 (or F6 if you are using eclipse settings) to move to next line, to move to next break-point you can press F9(or F8 if you are using eclipse settings). this way to can check all the functions being called.
This break-point method is really helpful if you just want to make sure that a particular function is being called.
Other than this if you still insist to know the details of all the functions you can store the stacktrace.
final StackTraceElement[] trace = new Throwable().getStackTrace())
StackTraceElement STrace = trace[1];
String className = STrace.getMethodName();
I want to create a condition to wait for a broadcast upon a button press
right now I am just doing solo.sleep(10000)
but I dont want to sleep solo for nothing
How do I formulate the condition "broadcast received" ?
Ok explanations
Robotium Solo is an instrumentation framework with nice api
It has a method called "solo.waitForCondition(Condition, int timeout)"
I want to formulate (the word formulate means say what i want to say in correct words)
the correct condition that will tell me that the broadcast was indeed received
I want to write some code (I don't know which exactly) to know that the broadcast was indeed sent
for example, if i want to know that a button is now visible i would write
solo.waitForCondition(new Condition(){
public boolean isSatisfied(){
Button b = getActivity().findViewById(R.id.myButton);
return b.getVisibility() == View.VISIBLE;
}
}
now back to my question - What (not how, but what) do I write in order to know for sure that the broadcast was sent inside the isSatisfied method
I suppose you meant that you don't want to sleep for 10 seconds, if you get the broadcast earlier. What you can do is
long beginTime = new Date().getTime();
while (new Date().getTime() - beginTime < 10000) {
solo.sleep(500);
if (conditionMet) {
// Do something
break;
}
}
This way you can do these checks on smaller intervals.
Ok, so in fact this is more or less how waitForCondition is implemented. Unfortunately I don't think you can listen for events with robotium. What you can do is monitor the view hierarchy. In your case, there should be some difference to the views that is triggered when the button is clicked, so that is what you need to check for in the Condition (and your example does that).
This is if you don't want to edit the code you are testing. If you are willing to change the code, you can add an onClickListener() and in that you can set a view's Tag to a boolean for example. Later in robotium you can check for that tag for being set. This is however not good way to do it, because you are adding more code just for the sake of the tests.
I have developed Android LWP using RenderScript. Now I want to add Setting Page and I use Preferences to save the option values.
EG. Initial objects quantity is 10. Then user can change the objects quantity to 20.
I cannot update/refresh/reset/recall the RenderScript to regenerate with the new Setting. How to do it?
I have managed up to onSharedPreferenceChanged, but how to call it in order to regenerate the LWP with the new Setting just after user click?
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
//How to force the renderscript to update here
}
In fact, what I need to know is "How to refresh/clear any drawn object on renderscript?"
Because when setting has been changed, I need to redraw the objects again....
The best things I have managed to go so far is to set the quantity of the objects on the listener like this
private class SPListener implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
// TODO Auto-generated method stub
OBJ_COUNT = Integer.parseInt(Utility.getNoOfObjects(mContext));
mScript.set_gObjectsCount(OBJ_COUNT);
mScript.invoke_updateObjects();
}
}
But I got "double" drawn objects. I need to clear existing objects first before I set with new quantity of objects.
EG. Initial objects quantity is 10. Then user can change the objects quantity to 5.
What I got is still 10 objects....with 5 objects are drawn twice/duplicated on top of it. So 5 objects have darker color due this overlay drawn.
I don't use RenderScript, but in my live wallpapers, I keep a class of static variables for all my settings, and an OnPreferenceChangedListener that transfers my settings to that class. In my draw method of the live wallpaper, I just pull the current values of those static variables. Also, when your live wallpaper first starts, you need to tell the settings class to update all of its variables to current values.
Finally managed to fix it...Nothing wrong on the technique. The location to update is also correct on onSharedPreferenceChanged. But I manage to redraw everything perfectly now.
Everything I've read about Intents talks about using them to push data, or to start one Activity from another Activity. I want to pull data from an Activity that's already running.
The Tab Layout tutorial at http://developer.android.com/resources/tutorials/views/hello-tabwidget.html illustrates what I want to do. (My app is doing some engineering calculations instead, but the tutorial code provides a good analogy to my app.) The tutorial creates an app with three tabs, and each tab hosts a separate activity.
To expand on the example in the tutorial, suppose I select an artist in the Artists tab/activity. I want to be able to select the Albums tab/activity and have it display all the albums featuring that artist.
It seems to me that I need to use an Intent to do this. All of the tutorials I've found assume that I would create a "See albums" Button in the Artists tab/activity, and that pressing the Button would execute an Intent that starts the Albums activity and passes artistName.
I DO NOT want to create that Button. Real estate on the Artists layout is precious, and I have a perfectly good Albums tab, AND the HelloTabWidget activity already contains an intent to create the Albums tab.
Besides, a user will want to skip back and forth between Album and Artist in order to change artist selections, and the tabs are a perfectly good way to do this. There's no need to complicate the UI with another button.
So how can I have the Albums activity PULL artistName from the Artists activity when the Albums tab is selected (or the Albums layout is displayed), rather than have the Artists activity START Albums and PUSH the artistName?
Equivalents I can think of from other programming worlds:
Global variables. Discouraged in Android devt, right? And if they do exist, what are they called?
A getter, like artistName = Artists.getArtistName(); . I get the feeling that it's not that easy.
Writing to, and reading from, a file - that is, mass storage or non-volatile memory. I don't need the artistName value to be permanent. It will be reset to null every time the user launches the application.
So how is it done in the Android world? Do I use an Intent - and if so, how?
Global variables were the right answer.
I thought Java discouraged their use, but a couple of links that appeared in the "Related" links on the right margin of this window mentioned them directly. One was "Android: How to declare global variables?" and the other was "how to pass value betweeen two tab in android". Both pointed to the Application Class as the place to define global variables and methods. Armed with this new knowledge, I found an article called "Android Application Class" on the Xoriant blog that expanded on the StackOverflow answers.
It's best to review those three links first. I need to add some tips to what those authors have said.
Your Application class has to be in its own separate file. (That might be a "duh" to some people, but not to everybody.) Here's a good framework for an example called Something.java:
public class Something extends Application {
// Put application wide (global) variables here
// Constants are final, so they don't have to be private
// But other variables should be declared private;
// use getters/setters to access them
public final boolean FEET = false;
public final boolean METERS = true;
private boolean units = FEET;
#Override
public void onCreate() {
super.onCreate();
// Put any application wide (global) initialization here
}
// Put application wide (global) methods here
public boolean getUnits() {
return units;
}
public void setUnits(boolean whichOne) {
units = whichOne;
}
}
I'm using Eclipse with the ADT plug-in, in Windows XP. Eclipse doesn't always behave properly if you edit XML code directly, so it's best to open AndroidManifest.xml, then select the Application tab and enter your application name in the Name field. You don't need to put a dot or period in front of the name. Just type in the name of your class, like "Globals" or "MyApplication" or whatever. (Note that this is the default application in your Manifest. You don't have to create a separate <application></application> tag.
This step may not be necessary on an actual Android device, but it was necessary for the emulator: you need to use the getApplicationContext() command in every onCreate() and every method that will be accessing the global variables and methods. I tried to put it outside of onCreate() with the rest of my activity wide variables, and it didn't work. Putting it inside every method seems wasteful, but both the emulator and the Android device work fine with it that way. Here's a sample showing how I used it:
public void fooBar() {
// Access to global variables and methods
final Something s = (Something)getApplicationContext();
// ...
// This next line demonstrates both a global method and a global variable
if (s.getUnits() == s.FEET) {
// do something with feet
} else {
// do something with meters instead
}
// ...
}
Those were the only hiccups I encountered. The three references that I have listed, taken together, are otherwise pretty complete.
I have an image which I am processing, and I have two buttons, undo and redo. I need the code to undo/redo previous touch action if either of those two buttons are clicked. I know I have to use a stack. How should I implement it?
There are two main patterns for implementing Undo/Redo:
The "memento" pattern.
The "command" pattern.
1. Memento Pattern
The idea of the memento pattern is that you can save a copy of the entire internal state of an object (without violating encapsulation) to be restored later.
It would be used (for example) like this:
// Create your object that can be "undone"
ImageObject myImage = new ImageObject()
// Save an "undo" point.
var memento = myImage.CreateMemento();
// do a bunch of crazy stuff to the image...
// ...
// Restore to a previous state.
myImage.SetMemento(memento);
2. Command Pattern
The idea of the command pattern is to encapsulate the actions that are actually performed on an object. Each "action" (or, "command") can optionally know how to roll itself back. Alternatively, when a rollback needs to occur, the entire chain of commands can be executed again.
It would be used (for example) like this:
// Create your object that can be "undone"
ImageObject myImage = new ImageObject()
// Create a "select all" command
var command = new SelectAllCommand(myImage); // This does not actually execute the action.
// Apply the "select all" command to the image
selectAll.Execute(); // In this example, the selectAll command would "take note" of the selection that it is overwriting.
// When needed, rollback:
selectAll.Rollback(); // This would have the effect of restoring the previous selection.
It all depends what your touch events do in the first place. You have to abstract what your application does in response to the touches into a class that you can fill a Stack with. Then, the stack implementation is easy.
If it's image manipulation, it might take up too much memory to keep a whole stack of Bitmaps around. You'll probably get the infamous OutOfMemoryException after pushing two or three items onto your stack. What you'd probably be better off doing is abstract the actions available in your app and rebuilding on undo/redo. You're basically creating a stack of instruction sets. This makes it slower the larger your stack is, but if the images in memory are large it might be the only way to do it.
In the newer Android versions (22+) you could use a Snackbar. Here's small code fragment for listener:
public class MyUndoListener implements View.OnClickListener{
&Override
public void onClick(View v) {
// Code to undo the user's last action
}
}
and creating a message at the bottom of the screen for an "undo" action:
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout),
R.string.email_archived, Snackbar.LENGTH_SHORT);
mySnackbar.setAction(R.string.undo_string, new MyUndoListener());
mySnackbar.show();