RoboGuice 3.0(一)ピット入り編

11959 ワード

RoboGuiceって何?
Android上の依存注入フレームワーク.
依存注入とは何ですか?
字面から理解すると,このフレームワークは2つのことを行い,1つ目は依存を除去し,2つ目は依存を注入することである.簡単に理解すると,オブジェクトの初期化をコンテナコントローラに委任する,すなわち依存を除去し,コンテナコントローラから依存を構築し,元のオブジェクトに注入する,すなわち注入依存である.
依存注入の利点は,オブジェクトが依存の初期化を気にする必要がなく,コードを極めて簡潔にすることである.
一.アクセス
在build.gradeに依存を追加
dependencies {
    provided 'org.roboguice:roboblender:3.0.1'
    compile 'org.roboguice:roboguice:3.0.1'
}

二.ビューインジェクション
コンタクト依存注入後、最も便利なのはビューの注入であり、以前に作成されたfindViewByIdのコードを省き、Activityのコード量が史上初の大掃除を完了した可能性がある.
ビュー注入には、次の3つのステップがあります.
  • RoboGuiceから受け継いだRoboActivityもちろんRoboFragmentActivityでも
  • Activityにcontent viewを追加(setContentViewは注釈を使用しても実現可能)
  • @InjectViewを使用してビュー
  • に注入
    @ContentView(R.layout.activity_main)
    public class MainActivity extends RoboFragmentActivity {
    
        @InjectView(R.id.text_test)
        TextView textView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            textView.setText("hello there!");
        }
    }

    このことから,ビュー注入はActivityにおけるコード量を大幅に簡略化した.
    同じ理屈でFragmentも同じです.ビュー注入はonViewCreated後に使用する必要があることに注意してください.
    public class AFragment extends RoboFragment {
    
        @InjectView(R.id.fragment_text)
        TextView textView;
    
        public static AFragment newInstance() {
            return new AFragment();
        }
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            return inflater.inflate(R.layout.a_fragment, container, false);
        }
    
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            textView.setText("Hi there!");
        }
    }

    三.しげんちゅうにゅう
    RoboGuiceはビュー注入のほか、リソース注入も提供しています.
    たとえばStringリソース、colorリソース、Animationリソースなどです.
    
    @ContentView(R.layout.activity_main)
    public class MainActivity extends RoboFragmentActivity {
    
        @InjectView(R.id.text_test)
        TextView textView;
    
        @InjectResource(R.string.app_name)
        String appName;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            textView.setText(appName);
        }
    }
    

    四.システムサービス注入
    Activityでは、振動や通知管理など、さまざまなシステムサービスを注入できます.
    完全なリストは次のとおりです.https://github.com/roboguice/roboguice/wiki/Provided-Injections
    これで、煩わしいgetSystemServiceというコードを書く必要はありません.
    @ContentView(R.layout.activity_main)
    public class MainActivity extends RoboFragmentActivity {
    
        @Inject
        Vibrator vibrator;
    
        @Inject
        NotificationManager notificationManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            vibrator.vibrate(500L);
            notificationManager.cancelAll();
        }
    }

    五.オブジェクト注入
    オブジェクトの注入はコードのデカップリング作業を最大限に完了した.フレームの中で手が一番遅いようなものです.
    Activityでユーザーがログイン状態を判断するなど、UserInfoがどのように初期化されているかを気にする必要はなく、ユーザーがログインしているかどうかを気にするシーンを想像します.
    実際の状況と結びつけて,例を挙げる.これはユーザー情報を格納するためのモデルです.
    public class UserInfo {
        private String userId;
        private String token;
    
        public String getUserId() {
            return userId;
        }
    
        public void setUserId(String userId) {
            this.userId = userId;
        }
    
        public String getToken() {
            return token;
        }
    
        public void setToken(String token) {
            this.token = token;
        }
    
        public boolean isLogin(){
            return !TextUtils.isEmpty(token);
        }
    }

    注記注入UserInfoを使用すると、RoboGuiceは初期化作業を完了し、初期化時にUserInfoのデフォルトの構築方法を呼び出します.
    これでuserInfo = new UserInfo()と書かずにオブジェクトを操作しました.
    @ContentView(R.layout.activity_main)
    public class MainActivity extends RoboFragmentActivity {
    
        @Inject
        UserInfo userInfo;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
            userId = sharedPreferences.getString("userId", "");
            token = sharedPreferences.getString("token", "");
            String userId = sharedPreferences.getString("userId", "");
            String token = sharedPreferences.getString("token", "");
            userInfo.setUserId(userId);
            userInfo.setToken(token);
        }
    }

    しかし、onCreate内部のユーザー情報を取得するコードは確かに醜い.Activityでは、ActivityのContextに依存しているため、ページに関連しない初期化作業を完了する必要がある.これは、オブジェクト内のメンバーを初期化するときにオブジェクトのいくつかのプロパティが必要な場合、コンテナにプロパティを渡してメンバーの初期化を担当する管理を巧みに行うことは難しいことに相当します.
    では、このような醜いコードをどう処理すればいいのでしょうか.
    RoboGuiceは、オブジェクト内のメンバーの初期化に必要なプロパティをカプセル化し、コンテナ管理者にコミットする機能を提供します.これにより、オブジェクトのプロパティに依存するメンバーの初期化プロセスがオブジェクトから完全に離れ、成功した後にオブジェクトに注入されます.
    Talk is cheap! Show me the code.
    RoboGuiceのActivityでは、ページ内のContextのようなコンテナ管理者がデフォルトで提供している属性が設定されています.これにより、メンバーが初期化されると、@Injectを使用して構築方法をマークして、RoboGuiceがデフォルトの構築方法で初期化しないことを示すことができます.構築方法のパラメータ属性がActivityオブジェクトからコンテナ管理者にコミットされた場合、コンテナ管理者はこの構築方法で初期化されます.
    私たちは改装を経て、UserInfoとActivityはそうです.ここで@ContextSingleton注記は、Contextのライフサイクル破棄に伴ってUserInfoが破棄されることを示しており、ここで@Singletonに変更すると、UserInfoのライフサイクルはアプリケーション全体のライフサイクルとなり、両方のActivityが注釈を使用している場合、生成されるオブジェクトは同じになります.
    ここで注意したいのは、@ContextSingletonが不適切に使用されるとメモリが漏洩してしまうので、これは後で例を示します.
    @ContextSingleton
    public class UserInfo {
        private static final String TAG = "UserInfo";
        private Context context;
        private String userId;
        private String token;
    
        @Inject
        public UserInfo(Context context) {
            this.context = context;
            init();
        }
    
        private void init() {
            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
            userId = sharedPreferences.getString("userId", "");
            token = sharedPreferences.getString("token", "");
        }
    
        public String getUserId() {
            return userId;
        }
    
        public void setUserId(String userId) {
            this.userId = userId;
        }
    
        public String getToken() {
            return token;
        }
    
        public void setToken(String token) {
            this.token = token;
        }
    
        public boolean isLogin(){
            return !TextUtils.isEmpty(token);
        }
    
        public void saveUserInfo(String userId) {
            SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
            editor.putString("userId", userId);
            editor.apply();
        }
    }
    @ContentView(R.layout.activity_main)
    public class MainActivity extends RoboFragmentActivity {
    
        @InjectView(R.id.text_test)
        TextView textView;
    
        @Inject
        UserInfo userInfo;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if(userInfo.isLogin()){
                textView.setText(userInfo.getUserId());
            } else {
                textView.setText("   ");
            }
        }
    }

    これで,ピット編は一段落し,RoboGuiceのビュー,リソース,システムサービス,オブジェクトなどの注入が開発に便利さをもたらし,モジュールの結合性も減少したことを主に説明した.