Archive for the ‘Java’ Category

Passing on objects through constructor

March 20, 2011

I am reading this nice article about architecting your application using Model View Presenter. In the application where you have lots of parts that work together and share some of the plumbings, the way you pass those plumbings around is that you have some centralized objects that are responsible for instantiating both the shared objects and those parts and you pass on the former to the latter  through their constructors:

// A part that asks for the infrastructure such as RPC service, event bus, etc..

public ContactsPresenter(ContactsServiceAsync rpcService,
HandlerManager eventBus, ContactsView<ContactDetails> view,
List<ColumnDefinition<ContactDetails>> columnDefinitions)

...

// The application controller, which constructs most of the parts that do the work.

public AppController(ContactsServiceAsync rpcService,
HandlerManager eventBus) {
this.eventBus = eventBus;
this.rpcService = rpcService;
bind();
}
...

// GWT's bootstrap process calls this "Main" that sets things in motion

public class Contacts implements EntryPoint {
public void onModuleLoad() {
ContactsServiceAsync rpcService = GWT.create(ContactsService.class);
HandlerManager eventBus = new HandlerManager(null);
AppController appViewer = new AppController(rpcService, eventBus);
appViewer.go(RootPanel.get());
}
}

The point is that a working bee (such as the ContactsPresenter) only needs to know the minimal (what he needs to know in order to get his work done). If he needs an rpcService, he does so by simply asking for a rpcService object in their constructors, or maybe have a setter property that can be used by a controller to assign a rpcService to it; but they should not set the rpcService object by themselves, like this:

// an anti-pattern ContactsPresenter object:
this.rpcService = ModelLocator.instance.rpcService;

Think about the scenario when the rpcService object later is to be moved to somewhere else; then we would have to change the code in all the working bees that use this rpcService. If we set the rpcService object through some centralized place (such as in module loader and appController), we would only need to change those few places. Another bad thing about doing so it that then your working bees start to know about too many details (like they know that the rpcService stores in the model locator singleton, which might change later on.) and start to dependent on those assumptions/details.  These couplings make change harder.

A better approach would be to inject those information from outside, such as managed by a few centralized objects, as we did from the beginning.

I think the real world analogy is that a working bee is expected to simply get the work done and not beyond. If he needs something, he would ask his manager, “I need a truck”. It’s the manager’s job to assign him a truck instead of him going out and looking for a truck by himself. (Or maybe not.)

P.S., Later I found out that a more trendy way of saying “to pass on objects” is “to inject the objects”. So the title of this post can then be rephrased as “constructor injection”.

ListView and ListActivity Demo

November 26, 2009

This is a slightly modified version at apiDemo. It demonstrates how you select multiple items on a ListView and display the results on a TextView.

main.xml layout (Note that the ListView has “choiceMode” set as “multipleChoice” and that the ListView has an id of “@android:id/list”):

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:orientation=”vertical”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
>
<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=” ”
android:id=”@+id/selection”
/>
<ListView
android:id=”@android:id/list”
android:choiceMode=”multipleChoice”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”/>
</LinearLayout>

Main java class:

package com.mh.android.test;

import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class ListAdapterTest extends ListActivity {

String[] items= {“lorem”, “ipsum”, “dolor”, “sit”, “amet”,
“consectetuer”, “adipiscing”, “elit”, “morbi”, “vel”,
“ligula”, “vitae”, “arcu”, “aliquet”, “mollis”,
“etiam”, “vel”, “erat”, “placerat”, “ante”,
“porttitor”, “sodales”, “pellentesque”, “augue”, “purus”};

TextView selection;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice,
items));
selection = (TextView) findViewById(R.id.selection);
}
@Override
protected void onListItemClick(ListView parent, View v, int position, long id) {
// Clear the TextView before we assign the new content.
selection.setText(” “);
// get array of booleans for which positions are selected in the items.
// This SparseBooleanArray object contains an array of boolean values paired with keys,
// which can be accessed using valueAt(index) and keyAt(index) respectively.
SparseBooleanArray chosen = parent.getCheckedItemPositions();
for(int i=0; i<chosen.size(); i++) {
Log.d(“selection”, “index: “+i+”; key: “+chosen.keyAt(i)+”; value: “+chosen.valueAt(i)+”; “+items[chosen.keyAt(i)]);
// if the item is selected by the user, we display it on the TextView.
if(chosen.valueAt(i)) {
selection.append(items[chosen.keyAt(i)]+” “);
}
}
}
}

Type of View.OnTouchListener

October 4, 2009

I found the documentation on the type of android.view.View.OnTouchListener misleading. It says: “Return true if the listener has consumed the event, false otherwise.”

For me, it looks like it should almost be the opposite:

“Return true if the event is allowed to propagate, false otherwise.”

//Sample code

public boolean onTouch(View v, evt:MotionEvent) {
switch(evt.getAction) {
case MotionEvent.ACTION_DOWN:
return true; // should allow propagate since we need to handle it in MOTION_MOVE block
case MotionEvent.ACTION_MOVE:
Log.d(“TOUCH”, “historical size is “+getHistoricalSize());
return false;
default:
break;
}
return false;//for any motions other than DOWN, we choose to block them. Unless other code want to handle it.
}

Please do feel free to correct me if I am wrong. Thanks.

JumpStart Android 101 for absolute beginners

June 19, 2009

Running the examples that come with the SDK in Eclipse

Eclipse->Package Explorer->Right click->New ->Android Project->Contents->Create project from existing source->Location>Navigate to

<directory_of_your_android_SDK>/platforms/android-1.5/samples/ApiDemos>OK

Eclipse will populate other setting values such as “Project name” and “Build Target” for you.:)

Local resource page (index.html)

<directory_of_your_android_SDK>/docs/index.html

just in case you don’t have/just lost/are having creeping internet but are desperate to look up the documentation to get something done ASAP so that you can go home;)

Using Android SDK 1.5 emulator with proxy in Eclipse 3.45

June 19, 2009

Go to Package Explorer -> Right click your Android project ->Run As->Run Configurations.

Under Android Application on the left column, select your project -> on the right column, where you see Android | Target | Common tabs ->

Select Target -> on the bottom “Additional Emulator Command Line Options”->

-http-proxy http://wwwgateProxy.com:1080 -debug-proxy http://wwwgateProxy.com:1080

->Run/Close.

Android SDK 1.5 with Eclipse 3.4 on Ubuntu 8.x

May 23, 2009

1. I am on Ubuntu 8.10 which seems to only support Eclipse 3.2 from Synaptic Package Manager. Since I installed both Eclipse and the IcedTea OpenJDK/JRE from Synaptic, I found out later that Android Dev tool actually needed the Sun JDK in order to use its Layout Editor (otherwise you won’t be able to use Android Layout Editor to edit xml files under res/layout folder. The error was java.awt.font wasn’t found something like that.) What I ended up doing was I uninstalled both Eclipse and IcedTea distribution of JDK (openjdk-6-jdk) from Synaptic, otherwise the newly updated Eclipse will continue to use openjdk which prevented me from using Android Layout Editor.

2. Install Sun’s Java (both jre and jdk).

Every step described in the above article worked for me except I couldn’t get the first step work which was:

sudo apt-get install sun-java6-jdk

apt-get said it could not locate sun-java6-jdk something like that.

So I went with this:

sudo aptitude search sun-java

Which told also me it wasn’t able to find sun-java first time I ran it. But after I did

sudo aptitude

and ->Actions->Update package list

I got to install sun java:

sudo aptitude install sun-java6-jre sun-java6-jdk sun-java6-plugin sun-java6-fonts

I was very happy with aptitude as compared to Synaptic package manager because of the exotic flavor of the former. Besides it seems to be more stable and responsive to me based on my judgement.;)

However, during the adventure, I got confused as to how I could single/full-heartedly accept the license agreement which showed up as a pop up within shell. It turned out  I had to maximize the whole thing and scroll down and use TAB key to select “OK” in order to advance.

After all this settled down, I rebooted Ubuntu and made sure that icedTea no longer took over the java world:

java -version

I get

java version "1.6.0_13"

Java(TM) SE Runtime Environment (build 1.6.0_13-b03)

Java HotSpot(TM) Server VM (build 11.3-b02, mixed mode)

3. Install and setup Eclipse 3.4.

I manually downloaded Eclipse 3.4 from their site and unzip it into /usr/lib folder. Android dev page recommends Eclipse IDE for Java EE Developers, Eclipse IDE for Java Developers, or Eclipse for RCP/Plug-in Developers.

You may want to temporarily change the owner of the/usr/lib folder to yourself instead of root:

chown <user> /usr/lib

After you are done, go to Eclipse->Help->About Eclipse Platform->Configuration Details, you can see Eclipse is now using the Sun jdk/jre:

java.library.path=/usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/client:/usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386:/usr/lib/xulrunner-addons:/usr/lib/xulrunner-addons:/usr/lib/xulrunner-addons:/usr/java/packages/lib/i386:/lib:/usr/lib

java.runtime.name=Java(TM) SE Runtime Environment

java.runtime.version=1.6.0_10-b33

and

java.awt.graphicsenv=sun.awt.X11GraphicsEnvironment

4. Install Android Development Tool for Eclipse. I personally found/suspected that the http url is faster/more stable(?) than the https one, esp if you are in slow connection. If you are behind some firewall, you may want to set Eclipse’s proxy. Eclispe->Window->Preferences->General->Network Connections->…

5. Configure BASH to export the JAVA_HOME env variable, as well as path to Eclipse like so:

sudo gedit /home/<user>/.bashrc

# ~~~~~~~~~~~~~~~~~ JAVA (JDK,JRE) ~~~~~~~~~~~~~~~~~~~~~

export JAVA_HOME=’/usr/lib/jvm/java-6-sun-1.6.0.10′

export ANDROID_HOME=’/usr/lib/android-sdk-linux_x86-1.5_r2′

PATH=.:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$ANDROID_HOME/tools

alias eclipse=’java -jar /usr/lib/eclipse/startup.jar’

6. (Optional) Configure Eclipse JRE to the one we just installed from Sun. Eclipse->Window->Preferences->Java->Installed JREs->Add->Standard VM->/usr/lib/jvm/java-6-sun-1.6.0.10. And check this new one we just added.

7. You may want to run

Eclipse -clean

if you had some trouble with it during the process.

8. I guess that’s pretty much about it(?)!

9. Have a great weekend/holiday!

Android on Eclipse 101: “Instrument TestRunner not specified”

May 20, 2009

Hello Android,

I started poking into Android this Monday. I installed Android SDK and Eclipse  for JEE developers v3.4.2, following the instructions at the official Android dev site. “Hello Android” went pretty smoothly as I recall except for some minor confusions when I launched the project. I think it was something in regards to the “Android virtual device” but somehow I got thorough. Today when I tried to do the “Notepad” tutorial I got the same error. It was something like this:

“ERROR: Application does not specify a android.test.InstrumentationTestRunner instrumentation or does not declare uses-library android.test.runner” 

I googled this post here which seems to post back when the 1.5pre was out. And it turned out to be much easier with 1.5. So here is the trick.

The problem is that Eclipse doesn’t recoginize the AVD I created under DOS commandline:

android create avd –target 2 –name my_avd

What I did was I clicked the little mobile phone icon (the 16 bit color style somehow reminds me of DOOM II? on DOS) on the toolbar under the menue which says “Opens Android Virtual Device (AVD) Manager” (or alternatively you can go to Window->Android AVD Manager) -> “Create AVD” -> “Finish”.

From then on, the compiler hasn’t complained about the InstrumentationTestRunner.