컴파일 시 메모를 사용하여 ButterKnife 구현
그리고 ButterKnife의 원리도 알아야 한다.
그래서 ButterKnife 최초의 1.0 버전을 찾아서 그 원리를 배우고 모방해 봅시다.
최종 효과
Activity에서 메모 바인딩 컨트롤 사용
public class MainActivity extends AppCompatActivity {
@InjectView(R.id.tv)
public TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Views.inject(this);
mTextView.setText("TextView");
}
}
프레임은 주석에 따라 생성된 코드는 다음과 같다
public class MainActivity$$ViewInjector {
public static void inject(MainActivity activity) {
activity.mTextView = (android.widget.TextView) activity.findViewById(2131427413);
}
}
프로젝트 구조
app
바로 저희 안드로이드 프로젝트입니다.
annotation
정의 주해
InjectView
는 이 모듈에 놓습니다.compiler
콜아웃 파서, 코드 생성
api
Butterkinfe의 API를 정의합니다. 예를 들어 우리가 자주 사용하는 Butterknife입니다.bind()
annotation
Android Studio에서 File - New Module - Java Library를 클릭하여 새 Java Module
build.gradle 내용은 다음과 같다
apply plugin: 'java'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
그런 다음 메모를 정의합니다.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface InjectView {
int value();
}
compiler
주석이 생기면, 이어서 주석을 해석하고 코드를 만들어야 한다.
마찬가지로, Java Library,build.gradle의 정의는 다음과 같다
apply plugin: 'java'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
dependencies {
compile 'com.google.auto.service:auto-service:1.0-rc2'
compile project(':annotation')
}
Google의 auto-service 의존도가 여기에 도입되었습니다.META-INF 파일을 생성하는 데 유용합니다.
이어서 주해 해석기를 만들고 실현하는 방법
process
@AutoService(Processor.class)
public class AnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment env) {
return false;
}
}
이 방법에서 주로 몇 가지 일을 했다
api
Android Library 만들기
Views
클래스 만들기import android.app.Activity;
import java.lang.reflect.Method;
public class Views {
private Views() {
// No instances.
}
public static void inject(Activity activity) {
try {
Class> injector = Class.forName(activity.getClass().getName() + "$$ViewInjector");
Method inject = injector.getMethod("inject", activity.getClass());
inject.invoke(null, activity);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("Unable to inject views for activity " + activity, e);
}
}
}
왜냐하면 우리가 생성한 코드의 클래스 이름은
Activity +$$ViewInjector
이기 때문이다.예를 들어Activity명HelloActivity
이라면 생성된 코드의 클래스명은HelloActivity$$ViewInjector
이다.따라서 여기서 반사를 이용하여 클래스 이름의 규칙에 따라 우리가 생성한 클래스를 찾아 inject()
방법을 호출한다.물론 반사를 사용하지 않고 생성된 클래스
HelloActivity$$ViewInjector.inject(Activity activity)
를 직접 호출해도 된다.그러나 매번 주석이 끝날 때마다rebuild에서 프로젝트를 한 번만 하고 코드가 생성된 후에야 호출할 수 있다HelloActivity$$ViewInjector.inject(Activity activity)
.이렇게 하는 것도 귀찮으니 직접 주해를 쓰는 것이 좋겠다.app
build.gradle의 정의는 다음과 같다
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.okada.viewinject"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:24.2.1'
compile project(':annotation')
apt project(':compiler')
compile project(':api')
}
프로젝트의build에 있습니다.gradle의 정의는 다음과 같다
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
이제 메모를 사용할 수 있습니다.
public class MainActivity extends AppCompatActivity {
@InjectView(R.id.tv)
public TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Views.inject(this);
mTextView.setText("TextView");
}
}
그리고 Build - Rebuild Project를 클릭하면 app - build - generated - source - apt 폴더에서 생성된 코드를 볼 수 있습니다
프로젝트 소스
https://github.com/okadaNana/ViewInject
참조 소스
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.