Android 依赖注入框架RoboGuice

概述

在开发应用时一个基本原则是模块化,并且尽最大可能性地降低模块之间的耦合性。Dependency injection 大大降低了类之间的依赖性,可以通过annotation描述类之间的依赖性,避免了直接调用类似的构造函数或是使用Factory来参加所需的类,从而降低类或模块之间的耦合性,以提高代码重用并增强代码的可维护性。

Google Guice提供了Java平台上一个轻量级的 Dependency injection 框架,并可以支持开发Android应用。本指南将使用Android平台来说明Google Guice的用法。(其他类似框架有Dagger,Buffernife)

RoboGuice 为Android平台上基于Google Guice开发的一个库,可以大大简化Android应用开发的代码和一些繁琐重复的代码。比如代码中可能需要大量使用findViewById在XML中查找一个View,并将其强制转换到所需类型,onCreate 中可能有大量的类似代码。RoboGuice 允许使用annotation 的方式来描述id于View之间的关系,其余的工作由roboGuice库来完成。

RoboGuice主要功能:

  • 控件注入:用@InjectViews方法初始化控件,例如:@InjectView(R.id.textview1)TextView textView1。
  • 资源注入:用@InjectResources方法初始化资源,例如:@InjectResource(R.string.app_name)String name。
  • 系统服务注入:用@Inject方法初始化并获取系统服务,例如:@Inject LayoutInflater inflater。
  • POJO对象注入:用@Inject方法注入并初始化POJO对象,例如:@Inject Foo foo。

以下示例对比看看RoboGuice的作用:

不使用RoboGuice:

    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            name      = (TextView) findViewById(R.id.name);
            thumbnail = (ImageView) findViewById(R.id.thumbnail);
            loc       = (LocationManager) getSystemService(Activity.LOCATION_SERVICE);
            icon      = getResources().getDrawable(R.drawable.icon);
            myName    = getString(R.string.app_name);
            name.setText( "Hello, " + myName );
        }
    } 

使用RoboGuice:

 @ContentView(R.layout.main)
    class RoboWay extends RoboActivity {
        @InjectView(R.id.name)             TextView name;
        @InjectView(R.id.thumbnail)        ImageView thumbnail;
        @InjectResource(R.drawable.icon)   Drawable icon;
        @InjectResource(R.string.app_name) String myName;
        @Inject                            LocationManager loc; 

        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            name.setText( "Hello, " + myName );
        }
    } 

使用前准备工作

RoboGuice官方Demo: https://github.com/roboguice/roboguice/tree/master/astroboy

安装

方式一:添加依赖库:(不推荐,在androidStudio上报错,很诡异。不知道为什么)

方式二:在build.gradle中的dependecies片段中添加:(推荐)

dependencies {
    provided 'org.roboguice:roboblender:3.0'
    compile 'org.roboguice:roboguice:3.0'
}

参考https://github.com/roboguice/roboguice/wiki/InstallationNonMaven

继承类:

activities, services, and fragments都需要继承自RoboGuice提供的下列类:

  • RoboActivity
  • RoboListActivity
  • RoboExpandableListActivity
  • RoboMapActivity
  • RoboPreferenceActivity
  • RoboAccountAuthenticatorActivity
  • RoboActivityGroup
  • RoboTabActivity
  • RoboFragmentActivity
  • RoboLauncherActivity
  • RoboService
  • RoboIntentService
  • RoboFragment
  • RoboListFragment
  • RoboDialogFragment
  • etc.

Injection

  • Inherit from RoboActivity
  • Set your content view
  • Annotate your views with @InjectView
public class MyActivity extends RoboActivity {
        @InjectView(R.id.text1) TextView textView;

        @Override
        protected void onCreate( Bundle savedState ) {
            setContentView(R.layout.myactivity_layout);
            textView.setText("Hello!");
        }
    }

@ContentView注解:

  @ContentView(R.layout.myactivity_layout)
    public class MyActivity extends RoboActivity {
        @InjectView(R.id.text1) TextView textView;

        @Override
        protected void onCreate( Bundle savedState ) {
            textView.setText("Hello!");
        }
    }

将View注入[email protected]

由于Fragment中的依赖注入发生在onViewCreated()中,所以需要在onViewCreated中调用super.onViewCreate()之后才能使用注入的View.

注意这里的:onViewCreated是在onCreateView调用之后恢复保存的状态到View之前立马调用,

@InjectView TextView commentEditText;

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    commentEditText.setText("Some comment");
}

注入Resource到Activity:@InjectResource

public class MyActivity extends RoboActivity {
    @InjectResource(R.anim.my_animation) Animation myAnimation;
}

注入System Service:@Inject

class MyActivity extends RoboActivity {
    @Inject Vibrator vibrator;
    @Inject NotificationManager notificationManager;

注入POJO:@Inject

注意:需要提供一个无参数构造器

class MyActivity extends RoboActivity {
    @Inject Foo foo; // this will basically call new Foo();
}

当然如果不想使用默认构造器,可以注解构造器:

class Foo {
    Bar bar;
    @Inject
    public Foo(Bar bar) {
        this.bar = bar;
    }
}

也可以注解POJO的Field:

class Foo {
    @Inject Bar bar;

    // Roboguice doesn't need a constructor, but you might...
}

注入Singleton

前提:对单例类使用@Singleton

@Singleton //a single instance of Foo is now used though the whole app
class Foo {
}
class MyActivity extends RoboActivity {
    @Inject Foo foo; // this will basically call new Foo();
}

注意:这个单例一旦创建会一直驻留内存,其他类似的还有@ContextSingleton,@FragmentSingletion,他们的作用范围比较小,利于垃圾回收。

自定义Binding

public interface IFoo {}

public class Foo implements IFoo {}
public class MyActivity extends RoboActivity {
    //How to tell RoboGuice to inject an instance of Foo ?
    @Inject IFoo foo;
}

要想注入时绑定接口IFoo到Foo,实例化Foo.需要进行绑定。

步骤:

1.向AndroidManifest.xml中添加meta-data

<application ...>
    <meta-data android:name="roboguice.modules"
               android:value="com.example.MyModule,com.example.MyModule2" />
</application>

2.继承AbstractModule

public class MyModule extends AbstractModule {
    //a default constructor is fine for a Module

    public void bind() {
        bind(IFoo.class).to(Foo.class);
    }
}
public class MyModule2 extends AbstractModule {
    //if your module requires a context, add a constructor that will be passed a context.
    private Context context;

    //with RoboGuice 3.0, the constructor for AbstractModule will use an `Application`, not a `Context`
    public MyModule( Context context ) {
        this.context = context;
    }

    public void bind() {
        bind(IFoo.class).toInstance( new Foo(context));
    }
}

注入到Service与BroadcastReceiver:

public class MyService extends RoboService {

   @Inject ComputeFooModule computeFooModule;
public class MyBroadcastReceiver extends RoboBroadcastReceiver {

   @Inject ComputeFooModule computeFooModule;

注入到自定义View

class MyView extends View {
    @Inject Foo foo;
    @InjectView(R.id.my_view) TextView myView;

    public MyView(Context context) {
        inflate(context,R.layout.my_layout, this);
        RoboGuice.getInjector(getContext()).injectMembers(this);//注意这一行,为了使其正常工作。
    }

    public MyView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        inflate(context,R.layout.my_layout, this);
        RoboGuice.getInjector(getContext()).injectMembers(this);
    }

    public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
        inflate(context,R.layout.my_layout, this);
        RoboGuice.getInjector(getContext()).injectMembers(this);
    }

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();
        //All injections are available from here
        //in both cases of XML and programmatic creations (see below)
        myView.setText(foo.computeFoo());
    }
}

使用RoboGuice Event

public class MyActivity extends RoboActivity {

    // Any method with void return type and a single parameter with @Observes annotation
    // can be used as an event listener.  This one listens to onResume.
    public void doSomethingOnResume( @Observes OnResumeEvent onResume ) {
        Ln.d("Called doSomethingOnResume in onResume");
    }

    // As you might expect, some events can have parameters.  The OnCreate event
    // has the savedInstanceState parameter that Android passes to onCreate(Bundle)
    public void doSomethingElseOnCreate( @Observes OnCreateEvent onCreate ) {
        Ln.d("onCreate savedInstanceState is %s", onCreate.getSavedInstanceState())
   }

    // And of course, you can have multiple listeners for a given event.
    // Note that ordering of listener execution is indeterminate!
    public void xxx( @Observes OnCreateEvent onCreate ) {
        Ln.d("Hello, world!")
    }
}

本文还有很多特性没有介绍到,后续可能会进行补充。

参考:

http://www.oschina.net/p/roboguice

https://github.com/roboguice/roboguice/wiki

http://mobile.51cto.com/abased-426620.htm

时间: 2024-10-11 06:26:23

Android 依赖注入框架RoboGuice的相关文章

关于Android依赖注入框架ButterKnife和Dagger的简单比较

最近调研了Android平台可以使用的依赖注入框架.发现现在常用的有四种.Dagger.Butter Knife.RoboGuice.Android Annotations.经过一系列的比较,最后我们的选择 的范围缩小到Dagger.Butter Knife这2个框架上.其实在国内外使用的比较多的应该是Dagger.但是我觉得还是有点复杂了,再看jakewharton的blog时,他也提到了dagger,我 摘抄了他在stackoverflow上回答Difference between Dagg

Android 依赖注入函数库Roboguice(一)

Roboguice是一个用于Android应用的依赖注入框架,使用Google官方的Guice库位极大地简化了Android的依赖注入.使用他使编程变得更加简单有趣. 使用Roboguice需要几个jar点击下载 下载知道导入到自己的项目中 使用Roboguice是Activity页面需要继承RoboActivity /** * */ package com.example.roboguicetest; import com.google.inject.Inject; import robogu

Dagger——Android上的依赖注入框架

* 你也可以去Github查看这片文章 简介 在开发程序的时候,会用到各种对象,很多对象在使用之前都需要进行初始化.例如你要操作一个SharedPreference,你需要调用getSharedPreferences(String name,int mode)来获取一个对象,然后才能使用它.而如果这个对象会在多个Activity中被使用,你就需要在每个使用的场景中都写下同样的代码.这不仅麻烦,而且增加了出错的可能.dagger的用途就是:让你不需要初始化对象.换句话说,任何对象声明完了就能直接用

Android Dagger依赖注入框架浅析

今天接触了Dagger这套android的依赖注入框架(DI框架),感觉跟Spring 的IOC差不多吧.这个框架它的好处是它没有采用反射技术(Spring是用反射的),而是用预编译技术,因为基于反射的DI非常地耗用资源(空间,时间) 由于现在开发都是用Android Studio了,所以我这里大概讲下配置Dagger框架的开发环境,需要怎么做. (由于Android Studio中用Gradle,所以跟传统我们用Eclipse配置的话,直接导入jar包,有点不一样.) 在开始看我的博文前,希望

【十三】注入框架RoboGuice使用:(Logging via Ln)

上一篇我们简单的介绍了一下RoboGuice的使用([十二]注入框架RoboGuice使用:(Your First Injected ContentProvider)),今天我们来看下Log日志使用. Android应用通过会使用内置的android.util.log在Android控制台上面打印日志信息.RoboGuice也提供了另外的日志管理,你可能会想要使用. (一):  RoboGuice日志管理和通常的Log差不多,但也同样具备以下优点: ①:对于发布包来说,Debug and ver

【十】注入框架RoboGuice使用:(Your First Testcase)

上一篇我们简单的介绍了一下RoboGuice的使用([九]注入框架RoboGuice使用:(Your First Injected Service and BroadcastReceiver)),今天我们来看下测试用例(TestCase)的注入 RoboGuice使得我们更加容易实现可测试的Android应用程序,本文章就来详细解说下:当我们测试的时候,如何编写测试用例,已经从RoboGuice中获益.本文章使用Android Robolectric,适合大部分用Android标准测试的情况.

【十四】注入框架RoboGuice使用总结

在我们平时开发Android项目的时候例如经常需要使用各种View控件,然后进行声明,findViewById,并且进行强转.每次都要写这样的代码就显得非常繁琐,并且容易出错哦.那么针对这种情况且不限定于以上的这类情况,Dependency injection 可以大大降低了类之间的依赖性,可以通过annotation (Java)描述类之间的依赖性,避免了直接调用类似的构造函数或是使用Factory来参加所需的类,从而降低类或模块之间的耦合性,以提高代码重用并增强代码的可维护性.Google

【五】注入框架RoboGuice使用:(Your First POJO Injection)

上一篇我们简单的介绍了一下RoboGuice的使用([四]注入框架RoboGuice使用:(Your First System Service Injection)),今天我们来看下普通Java对象的使用注解的方法: (一)为了在Activity中普通Java对象使用注解,必须实现以下两个步骤: ①:创建继承RoboActivity的Activity ②:使用 @Inject来进行注解POJO(普通java对象) 在前面我们介绍了View控件,资源文件(Resources),系统服务(Syste

【四】注入框架RoboGuice使用:(Your First System Service Injection)

上一篇我们简单的介绍了一下RoboGuice的使用([三]注入框架RoboGuice使用:(Your First Resource Injection)),今天我们来看下系统服务的使用注解的方法: 为了在Activity中系统服务使用注解,必须实现以下两个步骤: ①:创建继承RoboActivity的Activity ②:使用 @Inject来进行注解系统服务 下面我们来实现一个例子,和上一篇文章例子差不多,我们需要进行实现系统服务,我们同样创建一个继承RoboActivity的Activity