I currently have developed an app with some GUI and network operations, but I need to make it more of a library without the GUI.
I know that there is a "is library" option under Properties/Android. But the question is: how to move the GUI elements out of the project to a different app, so that the library/project will have only java code; any suggestion ?
Thanks.
If you are making code into a library, you want to try and decouple it as much as you can from anything else. This makes it much more portable so that more people can use the library how they wish. Even though you are using this library just for yourself right now, later on you may wish to release it to others.
For example, maybe your code is like this currently:
public void computeSum(int a, int b) {
int sum = a + b;
mTextView.setText(String.valueOf(sum));
}
Right now this code is tightly coupled with mTextView. Instead, it makes sense to rewrite the code like this:
//In library
public int computeSum(int a, int b) {
return a+b;
}
and
//Somewhere in your app
mTextView.setText(String.valueOf(computeSum(3,4)));
This is a small change, but you can see that computeSum() is no longer coupled with mTextView. This makes it much easier to use throughout your project and even other projects. Now the computeSum() method is part of an API.
So for your network calls, try to decouple them from your GUI stuff either by using callbacks or return values.
In regards to your latest comment:
You could create a wrapper like so:
public class UIWrapper {
public Runnable runnable;
public SomeUiCallback callback;
}
And then use this in your AsyncTask:
public class YourTask extends AsyncTask<UIWrapper, Void, Void> {
SomeUiCallback mCallback;
protected void doInBackground(UIWrapper... wrapper) {
mCallback = UiWrapper.callback;
UIWrapper.runnable.run();
}
protected void onProgressUpdate() {
}
protected void onPostExecute() {
mCallback.runYourUiStuff();
}
}
I wrote that code quickly so it likely won't compile, but hopefully you get the idea. I think something like this would work, not sure if it's the most elegant solution. You can replace the Runnable with whatever you want to run in the thread.
So both UIWrapper and YourTask would reside in your library. You would create the UIWrapper and then use that in the YourTask.
Related
I'm developing a java component that needs to run both on the command line and as a Eclipse job. The execution can take a few minutes, so I want to inform the user what's happening. I don't want to have a dependency to the Eclipse progress monitor package in my "pure" java code.
How can I provide progress monitoring in the Eclipse job without "polluting" my java code with Eclipse depenendcies?
Write your own progress monitor interface that you use in your code, something like:
interface MyProgressMonitor
{
public void beginTask(String name, int totalWork);
public void done();
public boolean isCanceled();
public void worked(int work);
}
For the Java application you can use an implementation of this that does nothing.
For the Eclipse job use an implementation that delegates to the Eclipse IProgressMonitor:
class EclipseMyProgressMonitor implements MyProgressMonitor
{
private final IProgressMonitor monitor;
EclipseMyProgressMonitor(IProgressMonitor theMonitor)
{
monitor = theMonitor;
}
public void beginTask(String name, int totalWork)
{
monitor.beginTask(name, totalWork);
}
public void done()
{
monitor.done();
}
public boolean isCanceled()
{
return monitor.isCanceled();
}
public void worked(int work)
{
monitor.worked(work);
}
}
It shouldn't be that difficult. Create the java component in a separate project using just pure java. Then create the eclipse functionality responsible for starting the job, see this article for assistance. You eclise code will start a job, this will in turn call your java component.
Issues that will be difficult to handle:
The user may want to abort the operation, you should try to handle this gracefully in your component. If you are just doing computations, you could kill the job, but if you do something that may require clean up, such as writing a file, you will need some other way to deal with it.
Ideally you would like to report a correct and realiable progress to the user, but that will introduce a dependency to org.eclipse.core.runtime.IProgressMonitor which you may not want.
I have to communicate between an Android Activity and another Java class. In a very, very stripped down version of what I want, I want the Java Class to run, and when it's done, set some information. To get a more specific idea of what I want to happen:
Activity {
CallJavaClass(); // Doesn't return anything, would be very bad form
GetInfoFromJavaClass() // Once the JavaClass has finished what needs to be done
}
What I could do:
Set a global variable in JavaClass that my Activity can access. I'd rather not do it this way, as I would have to implement some kind of OnChangedListener on that object in the JavaClass.
Use an Interface with Setters/ Getters. The problem with this is my JavaClass is a Singleton, and most of its methods are static, which is a no-go when working with an Interface.
Create a separate class that handles these variables. I would rather keep it simple and not have to use a bunch of different classes to do this, though.
So what do you think would be the best solution? If needed (and probably will be), I can provide more information about what exactly I want done. Thanks for your help in advance.
Sounds like something you could use AsyncTask for http://developer.android.com/reference/android/os/AsyncTask.html
then again, it depends on the specifics of what you're going for
AsyncTask should resolve your problem:
private class myTask extends AsyncTask<Void, Void, Boolean> {
protected void onPreExecute() {
super.onPreExecute();
// do something before starting the AsyncTask
}
#Override
protected Boolean doInBackground(Void... params) {
// do what you want to do
return false;
}
protected void onPostExecute(Boolean success)
{
super.onPostExecute(success);
// do something right after you finish the "doInBackground"
}
}
I have read several articles on this site, and several books about Handlers, Threads, HandlerThreads, Services, SyncAdapters, ContentProviders and on and on. There seems like a lot of different options and I don't know which is appropriate for my project.
I have a simple project that will connect to a simple REST web service when the app starts for the very first time. It will download some JSON data and show this in a list. The user may then edit this data, and after hitting "save" the app will send a POST to the web service with the updated data. The user may also instigate a "sync" manually which will check for any new data. Finally, the app should check the web service periodically to see if there's more data.
I started with a Content Provider but it seemed really overkill (and complicated) tho I'm sure it would eventually work. I then tried a Thread, but Android suggests using AsyncTask or Handlers instead. I have been playing around with them (putting them in a service), and both will do what I want (using a timer to initiate a sync every X minutes) but I don't know if this is the best way of handling this. I am worried because this project may grow to incorporate much more, and I don't want to choose an option that will limit me in the future, but I also don't want to invest tons of hours into something that's overkill.
Can anyone help?
Let's just start with what that whole keep it simple paradigm.
AsyncTask would be something like this:
public class MyAsyncTask extends AsyncTask<Void, Void, Data> {
public interface OnDone {
public void onDone(Data data);
}
private final OnDone mDone;
public MyAsyncTask(OnDone onDone) {
mDone = onDone;
}
public Data doInBackground(Void v) {
// Download and parse your JSON in the background
}
public void onPostExecute(Data data) {
mOnDone.onDone(data);
}
}
public class OnDoneImpl .... implements OnDone, Runnable {
...
// Just need a context in scope some how, an activity, the application whatever.
Context mContext;
public void onDone(Data data) {
updateList(data);
scheduleAgainInXMinutes(TIME_TILL_REFRESH);
}
public void scheduleAgainInXMinutes(long millis) {
// probably want to use an Alarm service but can always use a handler;
new Handler().postDelayed(this, millis);
}
public void run() {
new MyAsyncTask(this).execute();
}
}
Coming from a non-Java background, I find myself writing a lot of View classes with extensive functionality (in an effort to be portable), that don't necessarily fit nicely into the Android FW setup as far as maintenance - for example, I might have a widget that does something on a interval that I want to stop and clean up when an Activity is paused/stopped/destroyed. Generally I can manage this by just calling a public method on the widget from the containing Activity, but A) sometimes this gets pretty deep, and having to create a public method to access a child in every parent can get ugly, and B) requires extra (uneeded?) attention.
I'm considering using an approach like a global delegate to manage this kind of thing, but have read a lot of warnings about this sort of approach - would something like the class that follows have any inherent flaws that I might be missing?
import java.util.HashMap;
import java.util.HashSet;
public class ActiveRegistry {
private static final ActiveRegistry instance = new ActiveRegistry();
public static ActiveRegistry getInstance(){
return instance;
}
private HashMap<String, HashSet<Runnable>> registry = new HashMap<String, HashSet<Runnable>>();
private ActiveRegistry(){
}
public void register(String key, Runnable runnable){
if(!registry.containsKey(key)){
HashSet<Runnable> list = new HashSet<Runnable>();
registry.put(key, list);
}
HashSet<Runnable> list = registry.get(key);
list.add(runnable);
}
public void execute(String key){
if(registry.containsKey(key)){
HashSet<Runnable> list = registry.get(key);
for(Runnable runnable : list){
runnable.run();
}
}
}
}
Use might be something like...
A View has something that needs to be cleaned up. On instantiation, register it... ActiveRegistry.getInstance().register("paused", someRunnableThatCleansUpStuff)
Extend Activity so that onPause calls ActiveRegistry.getInstance().execute("paused");
You are doing way more work than you need to. Using Fragments (from the support package, if you want to ensure backwards compatibility with older versions of android), will make your life a whole lot easier. Each fragment is embedded in an activity and has a lifecycle that is directly linked with its host activity's lifecycle. Using them should significantly reduce the complexity of your code, as most of what you are currently worrying about will be managed by the system instead.
I'm totally new to posting questions on here, however I have been reading a lot on here for years. Normally I always am able to find my answers by thoroughly searching the web, but this time I am at a loss...
After having spent yet another day of trying to figure out why this is not working I decided to ask for help, hoping you guys can give me a few pointers, or better, a solution.
The problem:
In an Android game I have come to the point where I have to make the application remember its state when a user e.g. presses the HOME-screen button. After some searches I realised that in order to make my classes initialize back to their appropriate states after re-opening the application I had to support the Parcelable interface to pass them with the Bundle.
In my onStop and onStart functions I respectively save and restore the game state to and from a Bundle, however when I call the putParcelable and getParcelable functions on the Bundle the object's writeToParcel and createFromParcel functions are never called.
Fearing that this may have been due to the relative complexity of the game I figured I had best create a very simple application to try to get it to work.
Based on many Parcelable examples I have seen online, this became my class:
public class ParcelableTest implements Parcelable {
int id;
public ParcelableTest(int newID)
{
id = newID;
}
private ParcelableTest(Parcel in) {
readFromParcel(in);
}
public void writeToParcel(Parcel out, int arg1) {
writeToParcel(out);
}
public void writeToParcel(Parcel out) {
Log.v("ParcelableTest","Writing to parcel");
out.writeInt(id);
}
public void readFromParcel(Parcel in) {
id = in.readInt();
}
public int describeContents() {
return 0;
}
public static final Parcelable.Creator<ParcelableTest> CREATOR = new
Parcelable.Creator<ParcelableTest>() {
public ParcelableTest createFromParcel(Parcel in) {
Log.v("ParcelableTest","Creating from parcel");
return new ParcelableTest(in);
}
public ParcelableTest[] newArray(int size) {
return new ParcelableTest[size];
}
};
}
And from my Main activity I would call the following functions to save / restore the data:
public Bundle saveToBundle(Bundle savedState)
{
savedState.putParcelable("Test1",mTest1);
savedState.putParcelable("Test2",mTest2);
return savedState;
}
public void restoreFromBundle(Bundle savedState)
{
mTest1 = savedState.getParcelable("Test1");
mTest2 = savedState.getParcelable("Test2");
}
But for some reason neither of the functions (with the putParcelable and getParcelable functions) will result in the appropriate Parcelable calls in my test class.
The strangest thing is that it does somehow read the correct values (I have tried with more variables in the class), but my debugging and my log shows that tha application never gets to writeToParcel and createFromParcel.
What am I missing here?
Any help / thoughts would be appreciated.
Apparently the Android Bundle class does not adhere to the parcelable protocol that instead is followed during IPC marshalling.
Instead, it seems like the Bundle implementation just writes and reads the Parcelable object into its own internal map by means of reflection. From a test we did, it seems that the Bundle writes/reads every field defined in your Parcelable-derived class, just because you have declared those fields.
Technically, the documentation doesn't say that writeToParcel or createFromParcel are called from onSaveInstance. As a matter of fact, if you check the savedState in your code you are going to find that it is exactly the same object instance in both the save and the restore cases; it makes sense to avoid serialize-deserialize if you can. OTOH, the documentation doesn't say either that serialization is not done. The conclusion should be that you shouldn't depend on either case, just assume that you get the correct bundle.
Also, you may want to check http://developer.android.com/guide/topics/resources/runtime-changes.html
I confirm what superjos said.
On the saveToBundle event, Android bundle just stores the class's members per reflection and doesn't call the Parcelable functions.
I have lost one day on this problem! sad....
This is really bad .... This means you potentially stores a huge amount of data for nothing using this way.