【移動應(yīng)用開發(fā)技術(shù)】3000行代碼怎樣簡化成300行?來一文來教你_第1頁
【移動應(yīng)用開發(fā)技術(shù)】3000行代碼怎樣簡化成300行?來一文來教你_第2頁
【移動應(yīng)用開發(fā)技術(shù)】3000行代碼怎樣簡化成300行?來一文來教你_第3頁
【移動應(yīng)用開發(fā)技術(shù)】3000行代碼怎樣簡化成300行?來一文來教你_第4頁
【移動應(yīng)用開發(fā)技術(shù)】3000行代碼怎樣簡化成300行?來一文來教你_第5頁
已閱讀5頁,還剩10頁未讀 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】3000行代碼怎樣簡化成300行?來,一文來教你!

前言

APT(AnnotationProcessorTool)是用來處理注解的,即注解處理器。

APT

在編譯器會掃描處理源代碼中的注解,我們可以使用這些注解,然后利用

APT自動生成

Java代碼,減少模板代碼,提升編碼效率,使源碼更加簡潔,可讀性更高。1、具體場景下面我將會以項目中常見的intent頁面跳轉(zhuǎn)為例,給大家演示一下,如何自動生成

intent代碼,以及對

getIntent的參數(shù)自動賦值。

要實(shí)現(xiàn)上面這個功能我們需要了解

APT、以及

JavaPoet。如果不太了解的同學(xué)可以先去了解一下。要實(shí)現(xiàn)上面這個功能我們需要了解

APT、以及

JavaPoet。如果不太了解的同學(xué)可以先去了解一下。

常用寫法

Intent

intent

=

new

Intent(this,OtherActivity.class);

intent.putExtra("name",name);

intent.putExtra("gender",gender);

startActivity(intent);

數(shù)據(jù)獲取

String

name

=

getIntent().getStringExtra("name",name);

String

gender

=

getIntent().getStringExtra("gender",gender);上述代碼很必要但重復(fù)性又很高,寫多了會煩,又浪費(fèi)時間。并且在數(shù)據(jù)傳遞與獲取時

key

值都需要保持一致,這又需要我們新建很多的常量。所以,這里我們希望上述的數(shù)據(jù)傳遞與獲取可以自動生成。

為了實(shí)現(xiàn)這個需求,我們需要實(shí)現(xiàn)如下功能:

1)自動為

OtherActivity類生成一個叫做

OtherActivityAutoBundle

的類

2)使用建造者模式為變量賦值

3)支持

startActivity

startActivityForResult

跳轉(zhuǎn)

4)支持調(diào)用一個方法即可解析

Intent

傳遞的數(shù)據(jù),并賦值給跳轉(zhuǎn)的

Activity

中的變量

我們需要自動化如下代碼:

new

OtherActivityAutoBundle()

.name("小明")

.gender("男")

.start(this);//或

startActivityForResult(this,requestCode)

在OtherActivity中,自動為變量賦值:

new

OtherActivityAutoBundle().bindIntentData(this,getIntent());

a、創(chuàng)建一個JavaLibrary,并創(chuàng)建注解類

例如:

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.CLASS)

public

@interface

AutoBundle

{

boolean

exclude()

default

false;//不參與

intent、bundle

傳值

boolean

addFlags()

default

false;//添加

activity

啟動方式

boolean

isCloseFromActivity()

default

false;//是否關(guān)閉

FromActivity

boolean

isBundle()

default

false;//是否使用

Bundle

對象傳值

boolean

isSerializable()

default

false;//是否是

Serializable

類型

boolean

isParcelable()

default

false;//是否是

Parcelable

類型

boolean

isParcelableArray()

default

false;//是否是

ParcelableArray

類型

boolean

isParcelableArrayList()

default

false;//是否是

ParcelableArrayList

類型

}

b、再創(chuàng)建一個JavaLibrary,并將上一步JavaLibrary添加進(jìn)來

此時,我們還需要在該Library中創(chuàng)建

resources

文件夾;接著在

resources

中創(chuàng)建

META-INF

services

兩個文件夾;然后在

services

中創(chuàng)建一個名為

cessing.Processor

的文件。最后在該文件中寫入我們注解處理器的全路徑。此時,我們還需要在該Library中創(chuàng)建

resources

文件夾;接著在

resources

中創(chuàng)建

META-INF

services

兩個文件夾;然后在

services

中創(chuàng)建一個名為

cessing.Processor

的文件。最后在該文件中寫入我們注解處理器的全路徑。

這里我們也可以使用自動化工具

implementation'com.google.auto.service:auto-service:1.0-rc2'

感興趣的去搜一下具體用法這里我們也可以使用自動化工具

implementation'com.google.auto.service:auto-service:1.0-rc2'

感興趣的去搜一下具體用法

public

class

AutoBundleProcessor

extends

AbstractProcessor

{

}在創(chuàng)建

AutoBundleProcessor

后,我們需要重寫幾個方法

@Override

public

synchronized

void

init(ProcessingEnvironment

ev)

{

}

在編譯開始時首先會回調(diào)此方法,在這里,我們可以獲取一些實(shí)例為后面做準(zhǔn)備。在編譯開始時首先會回調(diào)此方法,在這里,我們可以獲取一些實(shí)例為后面做準(zhǔn)備。

@Override

public

boolean

process(Set<?

extends

TypeElement>

set,

RoundEnvironment

rev)

{

}

在該方法中,我們能夠獲取需要的類、變量、注解等相關(guān)信息,后面我們會利用這些來生成代碼在該方法中,我們能夠獲取需要的類、變量、注解等相關(guān)信息,后面我們會利用這些來生成代碼

@Override

public

Set<String>

getSupportedAnnotationTypes()

{

}

該方法中我們可以指定具體需要處理哪些注解該方法中我們可以指定具體需要處理哪些注解接著我們需要使用到

Elements、

Filer、

Name、

TypeMirror

對象

Elements:對

Element

對象進(jìn)行操作

Filer:文件操作接口,它可以創(chuàng)建

Java

文件

Name:表示類名、方法名

TypeMirror:表示數(shù)據(jù)類型。如

int、

String、以及自定義數(shù)據(jù)類型

下面我們可以獲取被

@AutoBundle

注解元素的相關(guān)信息:

Set<?

extends

Element>

elementsAnnotatedWith

=

rev.getElementsAnnotatedWith(AutoBundle.class);

for

(Element

element

:

elementsAnnotatedWith)

{

if

(element.getKind()

==

ElementKind.FIELD)

{

VariableElement

variableElement

=

(VariableElement)

element;

TypeElement

typeElement

=

(TypeElement)

variableElement.getEnclosingElement();

//類名

String

className

=

typeElement.getSimpleName().toString();

//包名

String

packageName

=

mElementUtils.getPackageOf(typeElement).getQualifiedName().toString();

AutoBundle

autoBundle

=

variableElement.getAnnotation(AutoBundle.class);

//變量名

Name

simpleName

=

variableElement.getSimpleName();

//變量類型

TypeMirror

typeMirror

=

variableElement.asType();

}

}例如:

變量:

gender、

type:java.lang.String變量:

gender、

type:java.lang.String其他變量亦是如此?,F(xiàn)在我們需要新建類來保存上面獲取的值。這里我們新建

FieldHolder

來保存變量類型、變量名以及其他信息。

FieldHolder

public

class

FieldHolder

{

private

String

variableName;//變量名

private

TypeMirror

clazz;//字段類型(如:String)

private

String

packageName;//包名

private

boolean

addFlags;//是否是添加

activity

啟動方式

private

boolean

exclude;//是否參與

intent、bundle

傳值

private

boolean

closeFromActivity;//是否關(guān)閉當(dāng)前

Activity

private

boolean

isBundle;//是否使用

Bundle

傳值

private

boolean

isSerializable;//是否實(shí)現(xiàn)

Serializable

接口的類

private

boolean

isParcelable;//是否是自定義類實(shí)現(xiàn)

Parcelable

接口

private

boolean

isParcelableArray;//是否是自定義類

ParcelableArray

類型

private

boolean

isParcelableArrayList;//是否是自定義類

ParcelableArrayList

類型

}4、下面我們需要使用JavaPoet生成Java文件

A、TypeSpec.Builder

主要用于生成類,這里的類包括的范圍比較廣,可以是一個

class、一個

interface

等等。主要用于生成類,這里的類包括的范圍比較廣,可以是一個

class、一個

interface

等等。

B、MethodSpec.Builder

主要用于生成類主要用于生成類

C、FieldSpec.Builder

主要用于生成成員變量主要用于生成成員變量

D、JavaFile.Builder

主要用來生成Java文件主要用來生成Java文件

E、其他方法

生成成員變量以及變量的set方法

TypeSpec.Builder

typeClass

=

TypeSpec.classBuilder(clazzName

+

"AutoBundle");

for

(FieldHolder

fieldHolder

:

fieldHolders)

{

packageName

=

fieldHolder.getPackageName();

FieldSpec

builder

=

FieldSpec.builder(ClassName.get(fieldHolder.getClazz()),

fieldHolder.getVariableName(),

Modifier.PRIVATE).build();

typeClass.addField(builder);

MethodSpec.Builder

buildParamMethod

=

MethodSpec.methodBuilder(String.format("%s",

fieldHolder.getVariableName()));

buildParamMethod.addParameter(ClassName.get(fieldHolder.getClazz()),

fieldHolder.getVariableName());

buildParamMethod.addStatement(String.format("this.%s=%s",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

buildParamMethod.addStatement(String.format("return

%s",

"this"));

buildParamMethod.addModifiers(Modifier.PUBLIC);

buildParamMethod.returns(ClassName.get(fieldHolder.getPackageName(),

clazzName

+

"AutoBundle"));

typeClass.addMethod(buildParamMethod.build());

}

生成的代碼:

public

class

OtherActivityAutoBundle

{

private

String

name;

private

String

gender;

public

OtherActivityAutoBundle

name(String

name)

{

=

name;

return

this;

}

public

OtherActivityAutoBundle

gender(String

gender)

{

this.gender

=

gender;

return

this;

}

}

生成start方法

private

void

generateCommonStart(MethodSpec.Builder

builderMethod,

List<FieldHolder>

fieldHolders,

String

clazzName)

{

builderMethod.addStatement(String.format("Intent

intent

=

new

Intent(context,%s.class)",

clazzName));

/**

生成頁面跳轉(zhuǎn)方法

*/

for

(FieldHolder

fieldHolder

:

fieldHolders)

{

String

fieldType

=

fieldHolder.getClazz().toString();

if

("android.os.Bundle".equals(fieldType))

{

builderMethod.addStatement(String.format("Bundle

%s

=

new

Bundle()",

fieldHolder.getVariableName()));

builderMethod.addStatement(String.format("intent.putExtra(\"%s\",%s)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

mAutoBundleField

=

fieldHolder.getVariableName();

}

else

if

(fieldHolder.isBundle()

&&

String.class.getName().equals(fieldType))

{

builderMethod.addStatement(String.format("%s.putString(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((boolean.class.getName().equals(fieldType)

||

Boolean.class.getName().equals(fieldType))

&&

fieldHolder.isBundle())

{

builderMethod.addStatement(String.format("%s.putBoolean(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((byte.class.getName().equals(fieldType)

||

Byte.class.getName().equals(fieldType))

&&

fieldHolder.isBundle())

{

builderMethod.addStatement(String.format("%s.putByte(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((char.class.getName().equals(fieldType)

||

Character.class.getName().equals(fieldType))

&&

fieldHolder.isBundle())

{

builderMethod.addStatement(String.format("%s.putChar(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((short.class.getName().equals(fieldType)

||

Short.class.getName().equals(fieldType))

&&

fieldHolder.isBundle())

{

builderMethod.addStatement(String.format("%s.putShort(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((int.class.getName().equals(fieldType)

||

Integer.class.getName().equals(fieldType))

&&

fieldHolder.isBundle())

{

builderMethod.addStatement(String.format("%s.putInt(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((long.class.getName().equals(fieldType)

||

Long.class.getName().equals(fieldType))

&&

fieldHolder.isBundle())

{

builderMethod.addStatement(String.format("%s.putLong(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((float.class.getName().equals(fieldType)

||

Float.class.getName().equals(fieldType))

&&

fieldHolder.isBundle())

{

builderMethod.addStatement(String.format("%s.putFloat(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((double.class.getName().equals(fieldType)

||

Double.class.getName().equals(fieldType))

&&

fieldHolder.isBundle())

{

builderMethod.addStatement(String.format("%s.putDouble(\"%s\",%s)",

mAutoBundleField,

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

}

結(jié)果

public

void

start(Context

context)

{

Intent

intent

=

new

Intent(context,

OtherActivity.class);

intent.putExtra("id",

id);

intent.putExtra("name",

name);

intent.putExtra("is",

is);

intent.putExtra("mByte",

mByte);

intent.putExtra("b",

b);

intent.putExtra("mShort",

mShort);

intent.putExtra("mLong",

mLong);

intent.putExtra("mFloat",

mFloat);

intent.putExtra("mDouble",

mDouble);

context.startActivity(intent);

}

生成bindIntentData

for

(FieldHolder

fieldHolder

:

fieldHolders)

{

packageName

=

fieldHolder.getPackageName();

TypeMirror

clazz

=

fieldHolder.getClazz();

String

fieldType

=

clazz.toString();

if

((boolean.class.getName().equals(fieldType)

||

Boolean.class.getName().equals(fieldType))

&&

!fieldHolder.isBundle()&&!fieldHolder.isExclude())

{

bindIntentMethod.addStatement(String.format("target.%s

=

intent.getBooleanExtra(\"%s\",false)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((byte.class.getName().equals(fieldType)

||

Byte.class.getName().equals(fieldType))

&&

!fieldHolder.isBundle())

{

bindIntentMethod.addStatement(String.format("target.%s

=

intent.getByteExtra(\"%s\",(byte)0)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((char.class.getName().equals(fieldType)

||

Character.class.getName().equals(fieldType))

&&

!fieldHolder.isBundle())

{

bindIntentMethod.addStatement(String.format("target.%s

=

intent.getCharExtra(\"%s\",(char)0)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((short.class.getName().equals(fieldType)

||

Short.class.getName().equals(fieldType))

&&

!fieldHolder.isBundle())

{

bindIntentMethod.addStatement(String.format("target.%s

=

intent.getShortExtra(\"%s\",(short)0)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((int.class.getName().equals(fieldType)

||

Integer.class.getName().equals(fieldType))

&&

!fieldHolder.isBundle()&&!fieldHolder.isExclude())

{

bindIntentMethod.addStatement(String.format("target.%s=intent.getIntExtra(\"%s\",0)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((long.class.getName().equals(fieldType)

||

Long.class.getName().equals(fieldType))

&&

!fieldHolder.isBundle())

{

bindIntentMethod.addStatement(String.format("target.%s=intent.getLongExtra(\"%s\",0)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((float.class.getName().equals(fieldType)

||

Float.class.getName().equals(fieldType))

&&

!fieldHolder.isBundle())

{

bindIntentMethod.addStatement(String.format("target.%s=intent.getFloatExtra(\"%s\",0)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

else

if

((double.class.getName().equals(fieldType)

||

Double.class.getName().equals(fieldType))

&&

!fieldHolder.isBundle())

{

bindIntentMethod.addStatement(String.format("target.%s=intent.getDoubleExtra(\"%s\",0)",

fieldHolder.getVariableName(),

fieldHolder.getVariableName()));

}

}

生成的結(jié)果

public

void

bindIntentData(OtherActivity

target,

Intent

intent)

{

target.id

=

intent.getIntExtra("id",

0);

=

intent.getStringExtra("name");

target.is

=

intent.getBooleanExtra("is",

false);

target.mByte

=

intent.getByteExtra("mByte",

(byte)

0);

target.b

=

intent.getCharExtra("b",

(char)

0);

target.mShort

=

intent.getShortExtra("mShort",

(short)

0);

target.mLong

=

intent.getLongExtra("mLong",

0);

target.mFloat

=

intent.getFloatExtra("mFloat",

0);

target.mDouble

=

intent.getDoubleExtra("mDouble",

0);

}

最后將生成好的Java代碼寫入文件

//與目標(biāo)

Class

放在同一個包下,解決

Class

屬性的可訪問性

JavaFile

javaFile

=

JavaFile.builder(packageName,

typeClass.build())

.build();

try

{

//生成

class

文件

javaFile.writeTo(mFiler);

}

catch

(IOException

e)

{

e.printStackTrace();

}生成的文件在

app/build/generated/ap_generated_sources/debug/out/包名/xxx

最后生成的代碼:

/**

*

This

codes

are

generated

automatically.

Do

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論