Android RoboGuice2 使用指南(4): 综合示例Astroboy

来源:互联网 发布:风驰网络加速器 官网 编辑:程序博客网 时间:2024/04/29 15:08

前面介绍了RogoGuice2.0的基本用法,其它使用可以参见RoboGuice1.1开发指南,2.0中提供了对Fragment,View(自定义View中使用注入)的支持,本博客不再一一介绍。

本例使用的是RoboGuice 开发包中的简单示例Astroboy(阿童木)。涉及的使用RoboGuice2.0 的一些常用方法。

本例下载(Eclipse项目)。

下面对项目中RoboGuice2的使用进行解释。因为本例没使用自定义绑定,所以无需使用res/values/roboguice.xml 定义Module. 如有自定义模块,可以参见Android RoboGuice2 使用指南(2): 第一个例子Hello World。

1. 类Astroboy

// There's only one Astroboy, so make it a @Singleton.// This means that there will be only one instance of Astroboy in the entire// app.// Any class that requires an instance of Astroboy will get the same instance.// This also means this class needs to be thread safe, of course@Singletonpublic class Astroboy {     // Because Astroboy is a Singleton, we can't directly inject the current    // Context since the current context may change depending on what activity    // is using Astroboy    // at the time. Instead we use the application context.    // Vibrator is bound to context.getSystemService(VIBRATOR_SERVICE) in    // DefaultRoboModule.    // Random has no special bindings, so Guice will create a new instance for    // us.    @Inject Application application;    @Inject Vibrator vibrator;    @Inject Random random;     public void say(String something) {        // Make a Toast, using the current context as returned by the Context        // Provider        Toast.makeText(application, "Astroboy says, \"" + something + "\"",                Toast.LENGTH_LONG).show();    }     public void brushTeeth() {        vibrator.vibrate(                new long[] { 0, 200, 50, 200, 50, 200, 50, 200, 50, 200, 50,                        200, 50, 200, 50, 200, 50, 200, 50, 200, 50, 200, 50, },                -1);    }     public String punch() {        final String expletives[] = new String[] { "POW!", "BANG!", "KERPOW!",                "OOF!" };        return expletives[random.nextInt(expletives.length)];    }}

程序中只希望使用一个Astroboy实例,因此可以使用@Singleton标注,此后任何使用

@Inject Astroboy astroboy;

注入的Astroboy都会指向同一个实例,这也是符合Singleton设计模式的。

@Inject Application application; 注入Application实例。参见Android RoboGuice 使用指南(15):Inject Context

@Inject Vibrator vibrator; 注入Android Vibrator实例,参见Android RoboGuice 使用指南(16):Standard Injection

@Inject Random random; 对于普通的Java 类型(POJO),如果该类具有缺省构造函数(不带参数的等),也可以使用RoboGuice自动注入实例。

因此当Astroboy创建时,RoboGuice 自动为application, vibrator, random 创建实例,无需使用new 或参数传入来构造它们。

2. 类AstroboyRemoteControl

/** * A class to control Astroboy remotely. * * This class uses the current context, so we must make it @ContextSingleton. * This means that there will be one AstroboyRemoteControl for every activity or * service that requires one. Note that we actually ask for the Activity, rather * than the Context (which is the same thing), because we need access to some * activity-related methods and this saves us from having to downcast to an * Activity manually. * * It also asks RoboGuice to inject the Astroboy instance so we can control him. * * What you'll learn in this class - What @ContextScope means and when to use it * - How to inject an Activity instead of a Context (which is really the same * thing) - How to use RoboGuice's convenient and flexible logging facility, Ln. */@ContextSingletonpublic class AstroboyRemoteControl {     // The Astroboy class has been decorated with @Singleton, so this instance    // of Astroboy will be the same instance used elsewhere in our app.    // Injecting an Activity is basically equivalent to "@Inject Context context",    // and thus also requires @ContextScope. If you wanted, you could also    // @Inject Application, Service, etc. wherever appropriate.    @Inject Astroboy astroboy;    @Inject Activity activity;     public void brushTeeth() {        // More info about logging available here:        // http://code.google.com/p/roboguice/wiki/Logging        Ln.d("Sent brushTeeth command to Astroboy");        astroboy.brushTeeth();    }     public void say(String something) {        Ln.d("Sent say(%s) command to Astroboy", something);        astroboy.say(something);    }     public void selfDestruct() {        Toast.makeText(                activity,                "Your evil remote control has exploded! Now Astroboy is FREEEEEEEEEE!",                Toast.LENGTH_LONG).show();        activity.finish();    }}

与Singleton类似的一个Scope标注为@ContextSingleton ,它表示对于每个Activity实例有一个实例,不同的activity对应不同的实例。

@Inject Astroboy astroboy; 注入同一个Astroboy实例(Singleton)。

@Inject Astroboy astroboy; 注入对应的Activity实例。

3. 类AstroboyMasterConsole

/** * This activity uses an AstroboyRemoteControl to control Astroboy remotely! * * What you'll learn in this class: - How to use @InjectView as a typesafe * version of findViewById() - How to inject plain old java objects as well * (POJOs) - When injection happens - Some basics about injection, including * when injection results in a call to an object's default constructor, versus * when it does something "special" like call getSystemService() */@ContentView(R.layout.main)public class AstroboyMasterConsole extends RoboActivity {     // Various views that we inject into the activity.    // Equivalent to calling findViewById() in your onCreate(), except more    // succinct    @InjectView(R.id.self_destruct) Button selfDestructButton;    @InjectView(R.id.say_text)  EditText sayText;    @InjectView(R.id.brush_teeth)   Button brushTeethButton;    @InjectView(tag = "fightevil")  Button fightEvilButton; // we can also use tags if we want     // Standard Guice injection of Plain Old Java Objects (POJOs)    // Guice will find or create the appropriate instance of AstroboyRemoteControl for us    // Since we haven't specified a special binding for AstroboyRemoteControl,    // Guice will create a new instance for us using AstroboyRemoteControl's default constructor.    // Contrast this with Vibrator, which is an Android service that is    // pre-bound by RoboGuice.    // Injecting a Vibrator will return a new instance of a Vibrator obtained by    // calling    // context.getSystemService(VIBRATOR_SERVICE). This is configured in    // DefaultRoboModule, which is    // used by default to configure every RoboGuice injector.    @Inject AstroboyRemoteControl remoteControl;    @Inject Vibrator vibrator;     @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState); // @Inject, @InjectResource, and                                            // @InjectExtra injection happens                                            // during super.onCreate()         sayText.setOnEditorActionListener(new OnEditorActionListener() {            public boolean onEditorAction(TextView textView, int i,                    KeyEvent keyEvent) {                 // Have the remoteControl tell Astroboy to say something                remoteControl.say(textView.getText().toString());                textView.setText(null);                return true;            }        });         brushTeethButton.setOnClickListener(new OnClickListener() {            public void onClick(View view) {                remoteControl.brushTeeth();            }        });         selfDestructButton.setOnClickListener(new OnClickListener() {            public void onClick(View view) {                 // Self destruct the remoteControl                vibrator.vibrate(2000);                remoteControl.selfDestruct();            }        });         // Fighting the forces of evil deserves its own activity        fightEvilButton.setOnClickListener(new OnClickListener() {            public void onClick(View view) {                startActivity(new Intent(AstroboyMasterConsole.this,                        FightForcesOfEvilActivity.class));            }        });     } }

AstroboyMasterConsole 为主Activity,要使用RoboGuice,则Activity需从RoboActivity派生,其它如Service,Fragment等可以参见Android RoboGuice 使用指南(13):RoboGuice 功能描述。

@InjectView(R.id.self_destruct) Button selfDestructButton; 注入View实例,功能同findViewById。 它的另外一种方法是使用Tag,如

@InjectView(tag = “fightevil”) Button fightEvilButton ,功能一样。

这个类使用@ContentView(R.layout.main) 为Activity指明ContentView,无需再调用setContentView.

4. 类FightForcesOfEvilActivity

/** * Things you'll learn in this class: - How to inject Resources - How to use * RoboAsyncTask to do background tasks with injection - What it means to be a @Singleton */public class FightForcesOfEvilActivity extends RoboActivity {     @InjectView(R.id.expletive) TextView expletiveText;     // You can also inject resources such as Strings, Drawables, and Animations    @InjectResource(R.anim.expletive_animation) Animation expletiveAnimation;     // AstroboyRemoteControl is annotated as @ContextSingleton, so the instance    // we get in FightForcesOfEvilActivity will be a different instance than    // the one we got in AstroboyMasterConsole    // @Inject AstroboyRemoteControl remoteControl;     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.fight_evil);         expletiveText.setAnimation(expletiveAnimation);        expletiveAnimation.start();         // Throw some punches        for (int i = 0; i < 10; ++i)            new AsyncPunch(this) {                @Override                protected void onSuccess(String expletive) throws Exception {                    expletiveText.setText(expletive);                }                 // We could also override onException() and onFinally() if we                // wanted             }.execute();     }     // This class will call Astroboy.punch() in the background    public static class AsyncPunch extends RoboAsyncTask<String> {         // Because Astroboy is a @Singleton, this will be the same        // instance that we inject elsewhere in our app.        // Random of course will be a new instance of java.util.Random, since        // we haven't specified any special binding instructions anywhere        @Inject Astroboy astroboy;        @Inject Random random;         public AsyncPunch(Context context) {            super(context);        }         public String call() throws Exception {            Thread.sleep(random.nextInt(5 * 1000));            return astroboy.punch();        }    }}

@InjectResource(R.anim.expletive_animation) Animation expletiveAnimation; 注入资源,可以参见Android RoboGuice 使用指南(18):Inject Resources。

从代码中可以看出使用RoboGuice 注入可以简化程序,运行结果如下图:



 

 


 


 

 

原创粉丝点击