-1
  1. How to properly manage code for android application? (for tasks/UI)
  2. How to separate user interface from code? (use class or packaged)
  3. How to add items to user interface from background thread/operation (correct way)? For example, i have TableLayout. How to properly add rows to that TableLayout? Create custom object (class) for my needs, then add items to object and then loop throughout that object and add items to TableLayout? Pass TableLayout as a reference?
  4. Better is to create separate class or package for data gathering? (connecting to data provider, get data, display it to user)

I searched around and found some ways to do background tasks.
- First is AsyncTask. Here is written, that AsyncTasks should ideally be used for short operations (a few seconds at the most.)
- Second I found is Handler.
- Is there another correct ways to do background tasks?

Witch way is correct for data gathering from WEB service (there may be some delays and lags)? If using Handler then how to pass data to UI thread?. And in most I am interested in question number 3.

Thanks.

Community
  • 1
  • 1
Guntis
  • 496
  • 1
  • 5
  • 19
  • 1
    Ask each question separately.. Only then, can you expect a *detailed* answer. – TheLostMind Jul 16 '14 at 07:10
  • Basically all 4 questions is in conjunction with each other. To write all code in one file/class, or split it. And general question is - how to do it in `correct` way. – Guntis Jul 16 '14 at 07:13
  • But nevertheless you should separate it to one exact question each with the correct context. Further more there isn't 'the correct way'. There are many, we only can advice you to the best way from our point of view... – alex Jul 16 '14 at 07:28

2 Answers2

1

There are many ways, to design the structure of an Android app. Your question is very general, so my answer is , too.

To structure your project, you can use the MVC pattern, that can easily used with Android:

  • Model: mostly keeps data, like in lists, arrays, strings etc
  • Controller: works with data of model, runs the logic
  • View: userinterface, that can display data from model and/or run logic from controller

The question, wether to separate with packages or classes can't be answered in general. Both are useful for many cases. In my point of view the following structure for an easy example would be useful:

  • [Package] view:
    • Activty1.java
    • Activty2.java
  • [Package] model:
    • Activty1DataModel.java
    • Activty2DataModel.java
  • [Package] controller:
    • Activty1Logic.java
    • Activty2Logic.java

Heavier tasks should be run on an AsyncTaks on Android and not on UIThread (e.g. because of GUI freezes). The AsyncTask runs operations in a new seperate thread. The onPostExecute method is executed after finishing the task and runs on the UI thread, so you can interact with the view from here directly.

For real long running tasks, you should use background services.

When you want to interact with an UI from another thread, you have to run the operations explicit on the UI thread e.g. like this:

MainActivity.this.runOnUiThread(new Runnable() {
    public void run() {
       Log.d("UI thread", "I am the UI thread");
   }
});

Another way to interact with the UI is to use Interfaces / Listeners.

To gather data from a web service, you can use an http client with an AsyncTask, but you must not run network operations from the UI thread (would result in an exception). Here is an example.

Next time please ask several questions in different posts, not all in one.

Community
  • 1
  • 1
alex
  • 5,516
  • 2
  • 36
  • 60
0

1). Question unclear. You would use own .java file for each class if you mean that.

2). Use multiple packages.

3). I'd say the best way to update UI from background is is using interfaces. Example of downloading an image (using a HttpClient):

  public class AsyncImageSetter extends AsyncTask<String, Void, Bitmap> {

private onImageLoaderListener listener;
private String msg, server;

public AsyncImageSetter(onImageLoaderListener listener) {
    this.listener = listener;
}
/* the onImageLoaded callback will be invoked on UI thread */
public interface onImageLoaderListener {
    void onImageLoaded(Bitmap bmp, String response);
}

@Override
protected Bitmap doInBackground(String... params) {
    HttpParams hparams = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(10000);
    HttpConnectionParams.setSoTimeout(10000);
    server = params[0];
    HttpGet get = new HttpGet(server);
    try {
        DefaultHttpClient client = new DefaultHttpClient(hparams));
        HttpResponse response = null;
        /** set cookies if you need it */
        CookieStore store = client.getCookieStore();
        HttpContext ctx = new BasicHttpContext();
        store.addCookie(yourSavedCookieObject);
        ctx.setAttribute(ClientContext.COOKIE_STORE, store);
        response = client.execute(get);
        msg = response.getStatusLine().toString();
        HttpEntity responseEntity = response.getEntity();
        BufferedHttpEntity httpEntity = null;
        try {
            httpEntity = new BufferedHttpEntity(responseEntity);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        InputStream imageStream = null;
        try {
            imageStream = httpEntity.getContent();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return BitmapFactory.decodeStream(imageStream);

    } catch (Exception ex) {
        ex.printStackTrace();
        //error handling
        return null;
    }
}

 /* use this method if your backend sets some pre-defined messages. /*
 /* In my case that would be "Warning */
private void checkResponse(HttpResponse response) {
    Header[] headers = response.getAllHeaders();
    final String target = "Warning";
    for (Header h : headers) {
        if (h.getName().equalsIgnoreCase(target)) {
            msg = h.getValue();
        } else {
            continue;
        }
    }

}

@Override
protected void onPostExecute(Bitmap result) {
    super.onPostExecute(result);
    /* now this callback is invoked on UI thread */
    /* if everything went without errors, you'll get an image and "HTTP 200 OK" in msg */
    if (listener != null) {
        listener.onImageLoaded(result, msg);
    }

 }

}

You'll need to pass a new onImageLoaderListener and override the onImageLoaded callback where you'll get your image and server message.

4). You'd basically use own package containing classes that perform some work in the background

Droidman
  • 11,485
  • 17
  • 93
  • 141