返回

深挖IOC注入技术:布局注入与控件注入的实战指南

Android

在探索了依赖注入和控制反转的基础后,让我们深入探究IOC注入技术。本篇指南将带你步步实践布局注入和控件注入。

运行时注入的解析

运行时注入在对象创建后进行依赖项的注入,相比编译时注入,它更加灵活。实现此注入技术有两种主要方式:布局注入和控件注入。

布局注入:

布局注入通过XML布局文件在视图中注入依赖项。它使用<viewstub>标签来指定注入位置。例如:

<ViewStub
    android:id="@+id/my_stub"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:inflatedId="@+id/my_injected_view"
    android:layout="@layout/my_injected_layout" />

在代码中,使用LayoutInflater将指定布局动态注入到ViewStub

View inflatedView = LayoutInflater.from(context).inflate(R.layout.my_injected_layout, null);
myStub.setVisibility(View.VISIBLE);

控件注入:

控件注入使用注解在控件上直接注入依赖项。它消除了使用XML布局文件的需要,简化了代码:

@InjectView(R.id.my_button)
Button myButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_layout);
    ButterKnife.inject(this);
    // ...
}

实战演练

示例项目:

创建一个新的Android Studio项目,并将其命名为"IOC注入实践"。

添加依赖项:

在app的build.gradle文件中添加以下依赖项:

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.jakewharton:butterknife:8.8.1'

布局注入:

在res/layout目录下创建my_layout.xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ViewStub
        android:id="@+id/my_stub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inflatedId="@+id/my_injected_view"
        android:layout="@layout/my_injected_layout" />
</RelativeLayout>

在res/layout目录下创建my_injected_layout.xml文件:

<TextView
    android:id="@+id/my_injected_text_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="This text view was injected via layout inflation." />

在MainActivity.java中注入依赖项:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_layout);

        // Inflate the injected layout
        View inflatedView = LayoutInflater.from(this).inflate(R.layout.my_injected_layout, null);

        // Add the inflated view to the parent view
        ViewStub myStub = findViewById(R.id.my_stub);
        myStub.setVisibility(View.VISIBLE);
        myStub.addView(inflatedView);
    }
}

控件注入:

在MainActivity.java中使用控件注入:

public class MainActivity extends AppCompatActivity {

    @InjectView(R.id.my_button)
    Button myButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_layout);
        ButterKnife.inject(this);

        // Use the injected button
        myButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ...
            }
        });
    }
}

编译并运行:

编译并运行项目。你会看到布局注入的文本视图和控件注入的按钮已成功添加到主布局中。