亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Andorid開(kāi)發(fā)中反射機(jī)制是怎么一回事

 更新時(shí)間:2022年11月03日 11:25:06   作者:broadview_java  
反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任何一個(gè)類(lèi),都可以知道這個(gè)類(lèi)的所有屬性和方法,對(duì)于任何一個(gè)對(duì)象,都可以調(diào)用它所有的方法和屬性,修改部分類(lèi)型信息,這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為Java的反射機(jī)制

1. 背景

在andorid開(kāi)發(fā)中,經(jīng)常遇見(jiàn)在某些工具類(lèi)中沒(méi)有Context上下文對(duì)象時(shí),一些系統(tǒng)服務(wù)的代理對(duì)象無(wú)法創(chuàng)建出來(lái),舉個(gè)例子:比如在源碼(framework/base/graphics/java/android/graphics)路徑下的Canvas.java Bitmap.javaPicture.java Paint.java 類(lèi)就沒(méi)有上下文對(duì)象。當(dāng)時(shí)有需要調(diào)用AMS的API獲取當(dāng)前界面activity的名稱作為判斷條件去修改這些工具類(lèi)中的參數(shù),但是這幾個(gè)工具類(lèi)中又沒(méi)有上下文對(duì)象,怎么辦呢?

一般情況下,獲取頂層activity名稱的方法如下:

//1. 獲取 AMS 的代理對(duì)象 ActivityManager
ActivityManager am = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
//2. 調(diào)用相關(guān)API 獲取頂層activity的名稱
String activityName = am.getRunningTasks(1).get(0).topActivity.getClassName();

上述代碼是在有上下文對(duì)象context的情況下,直接獲取。

而在上面提及到的Picture.java等類(lèi)中, 根本就沒(méi)有上下文,怎么搞? 這個(gè)時(shí)候我們通過(guò)java反射來(lái)實(shí)現(xiàn),接下來(lái),本篇文章就來(lái)講解一下java反射機(jī)制,并利用反射實(shí)現(xiàn)獲取頂層activity。

2. java反射

2.1 什么是反射

反射(Reflection)是程序的自我分析能力,通過(guò)反射可以確定類(lèi)中有哪些方法、有哪些構(gòu)造方法以及有哪些成員變量,在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為java語(yǔ)言的反射機(jī)制。

2.2 什么情況下要用反射

首先java是面向?qū)ο缶幊痰模f(wàn)物皆對(duì)象, 當(dāng)我們拿到這個(gè)類(lèi)對(duì)象后,就可以訪問(wèn)類(lèi)中的成員變量,調(diào)用類(lèi)中的方法了,但是呢?對(duì)于private變量和方法,它的訪問(wèn)權(quán)限作用域只在本類(lèi)中,在外部類(lèi)或者繼承類(lèi)中,就算你創(chuàng)建了該類(lèi)對(duì)象,也是無(wú)法直接調(diào)用的。來(lái)看下這個(gè)例子:

普通的一個(gè)User 類(lèi)

public class User {
    private String name = "墨子"; //私有變量
    public int age = 18;
    //私有方法
    private int test() {
        System.out.println("私有成員方法");
        return 1;
    }
    protected String test2() {
        System.out.println("protected成員方法");
        return "protected";
    }
    public static void main(String[] args) {
        //如果在本類(lèi)中創(chuàng)建了對(duì)象,則所有的方法和變量都可以直接訪問(wèn)
        User user = new User();
        System.out.println(user.name); //訪問(wèn)私有變量
        System.out.println(user.test());//調(diào)用私有方法
    }
}

打印結(jié)果如下:
墨子
私有成員方法
1

如果在外部?jī)?nèi)中創(chuàng)建該類(lèi)對(duì)象,還能直接訪問(wèn)私有方法和變量嗎? 測(cè)試一下:

public class PrivateTest {
    public static void main(String[] args) {
        User user = new User();
        //外部?jī)?nèi)中創(chuàng)建的對(duì)象直接私有變量  報(bào)錯(cuò)
        //System.out.println(user.name);
        //外部?jī)?nèi)中創(chuàng)建的對(duì)象,直接調(diào)用private方法,也報(bào)錯(cuò)
        //System.out.println(user.test());
        //但是可以直接訪問(wèn) protected public的方法和變量
        System.out.println(user.age);
        System.out.println(user.test2());
    }
}

 報(bào)錯(cuò)的兩行代碼注釋掉了,可以把代碼復(fù)制過(guò)去驗(yàn)證一下。

當(dāng)然了,在andorid開(kāi)發(fā)中,還有其他場(chǎng)景會(huì)使用到反射, 很多類(lèi)或方法中經(jīng)常加上了“@hide”注釋標(biāo)記,這些API是不允許在第三方應(yīng)用直接調(diào)用的比如:SystemProperties類(lèi)在android.os下,但這個(gè)類(lèi)是隱藏的,沒(méi)有系統(tǒng)權(quán)限(android:sharedUserId="android.uid.system")的app無(wú)法直接使用,只能通過(guò)java反射來(lái)調(diào)用。

還有 Andorid中動(dòng)態(tài)代理模式 , Android插件化(Hook)這些都會(huì)用到反射,這里不一一說(shuō)明,因?yàn)槊總€(gè)技術(shù)點(diǎn)都需要去深挖才能理解透徹。

2.3 反射的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1.可以調(diào)用私有方法、變量

2.可以調(diào)用隱藏api接口

3.能夠運(yùn)行時(shí)動(dòng)態(tài)獲取類(lèi)的實(shí)例,提高代碼靈活性

缺點(diǎn):

1.安全問(wèn)題:反射可以獲取到類(lèi)對(duì)應(yīng)的所有方法和屬性,如果存在外部調(diào)用的情況,可能出現(xiàn)超出預(yù)期的調(diào)用,從而導(dǎo)致安全風(fēng)險(xiǎn), 而且也破壞java面向?qū)ο缶幊痰姆庋b這一特性。

2.性能問(wèn)題:無(wú)論是通過(guò)字符串獲取Class、Method還是Field,都需要JVM的動(dòng)態(tài)鏈接機(jī)制動(dòng)態(tài)的進(jìn)行解析和匹配,勢(shì)必造成性能開(kāi)銷(xiāo)。每一次的反射調(diào)用都會(huì)造成Java安全機(jī)制進(jìn)行額外的安全性驗(yàn)證,造成性能開(kāi)銷(xiāo)。反射代碼使得許多JVM的運(yùn)行時(shí)優(yōu)化無(wú)法進(jìn)行。

3. Java反射機(jī)制API

Java反射機(jī)制API主要是 java.lang.Class類(lèi) 和 java.lang.reflect包。

類(lèi)說(shuō)明
java.lang.Class 代表整個(gè)字節(jié)碼。代表一個(gè)類(lèi)型,代表整個(gè)類(lèi)。
java.lang.reflect.Constructor 代表字節(jié)碼中的構(gòu)造方法字節(jié)碼。代表類(lèi)中的構(gòu)造方法。
java.lang.reflect.Method 代表字節(jié)碼中的方法字節(jié)碼。代表類(lèi)中的方法。
java.lang.reflect.Field 代表字節(jié)碼中的屬性字節(jié)碼。代表類(lèi)中的成員變量(靜態(tài)變量+實(shí)例變量)

3.1 獲取Class對(duì)象

方式說(shuō)明
對(duì)象.getClass(); 
類(lèi)名.class 
Class.forName(“類(lèi)的全路徑”);推薦此種寫(xiě)法
package com.example.javademo.reflect;
public class ClassObject {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一種: 對(duì)象.getClass();
        People people = new People();
        Class clazz1 = people.getClass();
        System.out.println(clazz1);
        //第二種: 類(lèi)名.class
        Class clazz2 = People.class;
        System.out.println(clazz2);
        //第三種: Class.forName(包名.類(lèi)名)
        Class clazz3 = Class.forName("com.example.javademo.reflect.People");
        System.out.println(clazz3);
    }
}

第一種:直接new出對(duì)象,然后通過(guò)對(duì)象獲取class對(duì)象, 但是你想想類(lèi)對(duì)象都可以直接new出來(lái),在外部?jī)?nèi)中除了private 變量和方法不能直接訪問(wèn)外,都可以直接調(diào)用,我還反射干嘛?寫(xiě)那么多代碼豈不是為難自己,沒(méi)事找事,不推薦!

第二種:通過(guò)類(lèi)名.class 獲取字節(jié)碼class對(duì)象,需要導(dǎo)入包,依賴性比較強(qiáng),不然會(huì)編譯報(bào)錯(cuò)

第三種:Class的靜態(tài)方法,安全性強(qiáng), 參數(shù)為:類(lèi)包名+類(lèi)名

運(yùn)行結(jié)果如下:

class com.example.javademo.reflect.People
class com.example.javademo.reflect.People
class com.example.javademo.reflect.People

三個(gè)都是同一個(gè)Class對(duì)象,在運(yùn)行期間,一個(gè)類(lèi),只有一個(gè)Class對(duì)象產(chǎn)生

3.2 反射調(diào)用類(lèi)構(gòu)造方法

方法名解釋說(shuō)明

方法名解釋說(shuō)明

public Constructor[] getConstructors()
所有"公有的"構(gòu)造方法
public Constructor getConstructor(Class... parameterTypes)獲取指定參數(shù)的共有構(gòu)造方法
public Constructor[] getDeclaredConstructors()獲取所有的構(gòu)造方法(包括私有、受保護(hù)、默認(rèn)、公有)
public Constructor getDeclaredConstructor(Class... parameterTypes):獲取"指定參數(shù)的構(gòu)造方法"可以是私有的,或受保護(hù)、默認(rèn)、公有;
 
newInstance(Object... initargs)使用此 Constructor 對(duì)象表示的構(gòu)造方法來(lái)創(chuàng)建該構(gòu)造方法的聲明類(lèi)的新實(shí)例,并用指定的初始化參數(shù)初始化該實(shí)例。 它的返回值是T類(lèi)型,所以newInstance是創(chuàng)建了一個(gè)構(gòu)造方法的聲名類(lèi)的新實(shí)例對(duì)象,相當(dāng)于People  p = new People();

我們看下Demo

package com.example.javademo.reflect;
public class People {
    private String name;
    private int age;
    public String sex;
    private long height;
    public People() {
        System.out.println("調(diào)用了public無(wú)參構(gòu)造方法 執(zhí)行完畢");
    }
    public People(String name) {
        this.name = name;
        System.out.println("調(diào)用public有參構(gòu)造方法 String:name = " + name);
    }
    private People(int age, String sex) {
        this.age = age;
        this.sex = sex;
        System.out.println("調(diào)用private有參數(shù)構(gòu)造方法 age :"+ age + "  sex:" + sex);
    }
    People(long height) {
        this.height = height;
        System.out.println("調(diào)用default有參數(shù)構(gòu)造方法 height :"+ height );
    }
}

反射測(cè)試類(lèi):

package com.example.javademo.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectPeople {
    public static void main(String[] args) {
        try {
            //獲取People class對(duì)象
            Class peopleclass = Class.forName("com.example.javademo.reflect.People");
            System.out.println("**********************獲取反射后類(lèi)對(duì)象*********************************");
            System.out.println("反射類(lèi)對(duì)象: " + peopleclass);
            //獲取所有構(gòu)造方法
            System.out.println("**********************打印所有構(gòu)造方法*********************************");
            Constructor[] conArray = peopleclass.getDeclaredConstructors();
            for(Constructor c : conArray){
                System.out.println(c);
            }
            System.out.println("**************第一種:通過(guò)反射調(diào)用默認(rèn)無(wú)參構(gòu)造方法并創(chuàng)建people類(lèi)實(shí)例對(duì)象***************************");
            //返回一個(gè) Constructor對(duì)象, 該對(duì)象反映Constructor對(duì)象表示的類(lèi)的指定的公共類(lèi)函數(shù)。
            Object constructorPublic = peopleclass.getConstructor();
            System.out.println("無(wú)參構(gòu)造方法的對(duì)象:" + peopleclass.getConstructor());
            //使用此 Constructor對(duì)象表示的構(gòu)造函數(shù),使用指定的初始化參數(shù)來(lái)創(chuàng)建和初始化構(gòu)造函數(shù)的聲明類(lèi)的新實(shí)例。
            //newInstance()方法內(nèi)部實(shí)際上調(diào)用了無(wú)參數(shù)構(gòu)造方法,必須保證無(wú)參構(gòu)造存在才可以
            Object peopleobject1 = ((Constructor) constructorPublic).newInstance();
            System.out.println("創(chuàng)建people1對(duì)象新實(shí)例: " + (People)peopleobject1);
            System.out.println("**************第二種:通過(guò)反射調(diào)用public有參構(gòu)造方法并創(chuàng)建People類(lèi)實(shí)例對(duì)象***************************");
            Object peopleobject2 = peopleclass.getConstructor(String.class).newInstance("甲方");
            System.out.println("創(chuàng)建people2對(duì)象新實(shí)例: " + (People)peopleobject2);
            System.out.println("**************第三種:通過(guò)反射調(diào)用private有參構(gòu)造方法并創(chuàng)建People類(lèi)實(shí)例對(duì)象***************************");
            //注意,如果訪問(wèn)protect private相關(guān)的構(gòu)造方法,需要用getDeclaredConstructor這個(gè)API
            //返回一個(gè) Constructor對(duì)象,該對(duì)象反映 Constructor對(duì)象表示的類(lèi)或接口的指定類(lèi)函數(shù)。
            Constructor constructorPrivate = peopleclass.getDeclaredConstructor(int.class, String.class);
            //訪問(wèn)私有構(gòu)造方法,這句話一定要寫(xiě),不然就會(huì)報(bào)錯(cuò)java.lang.IllegalAccessException
            constructorPrivate.setAccessible(true);
            System.out.println("有參private私有構(gòu)造方法的對(duì)象:" + peopleclass.getDeclaredConstructor(int.class, String.class));
            Object peopleobject3 = constructorPrivate.newInstance(20, "men");
            System.out.println("創(chuàng)建people3對(duì)象新實(shí)例: " + peopleobject3);
            System.out.println("**************第四種:通過(guò)反射調(diào)用default有參構(gòu)造方法并創(chuàng)建People類(lèi)實(shí)例對(duì)象***************************");
            Constructor constructorDefault = peopleclass.getDeclaredConstructor(long.class);
            //訪問(wèn)public protect default構(gòu)造方法,這句話可以不用寫(xiě)
            //constructorDefault.setAccessible(true);
            System.out.println("有參default構(gòu)造方法的對(duì)象:" + peopleclass.getDeclaredConstructor(long.class));
            Object peopleobject4 = constructorDefault.newInstance(185);
            System.out.println("創(chuàng)建people4對(duì)象新實(shí)例: " + peopleobject4);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

打印log:

**********************獲取反射后類(lèi)對(duì)象*********************************
反射類(lèi)對(duì)象: class com.example.javademo.reflect.People
**********************打印所有構(gòu)造方法*********************************
com.example.javademo.reflect.People(long)
private com.example.javademo.reflect.People(int,java.lang.String)
public com.example.javademo.reflect.People(java.lang.String)
public com.example.javademo.reflect.People()
**************第一種:通過(guò)反射調(diào)用默認(rèn)無(wú)參構(gòu)造方法并創(chuàng)建people類(lèi)實(shí)例對(duì)象***************************
無(wú)參構(gòu)造方法的對(duì)象:public com.example.javademo.reflect.People()
調(diào)用了public無(wú)參構(gòu)造方法 執(zhí)行完畢
創(chuàng)建people1對(duì)象新實(shí)例: com.example.javademo.reflect.People@2a139a55
**************第二種:通過(guò)反射調(diào)用public有參構(gòu)造方法并創(chuàng)建People類(lèi)實(shí)例對(duì)象***************************
調(diào)用public有參構(gòu)造方法 String:name = 甲方
創(chuàng)建people2對(duì)象新實(shí)例: com.example.javademo.reflect.People@15db9742
**************第三種:通過(guò)反射調(diào)用private有參構(gòu)造方法并創(chuàng)建People類(lèi)實(shí)例對(duì)象***************************
有參private私有構(gòu)造方法的對(duì)象:private com.example.javademo.reflect.People(int,java.lang.String)
調(diào)用private有參數(shù)構(gòu)造方法 age :20  sex:men
創(chuàng)建people3對(duì)象新實(shí)例: com.example.javademo.reflect.People@6d06d69c
**************第四種:通過(guò)反射調(diào)用default有參構(gòu)造方法并創(chuàng)建People類(lèi)實(shí)例對(duì)象***************************
有參default構(gòu)造方法的對(duì)象:com.example.javademo.reflect.People(long)
調(diào)用default有參數(shù)構(gòu)造方法 height :185
創(chuàng)建people4對(duì)象新實(shí)例: com.example.javademo.reflect.People@7852e922

通過(guò)上面的例子,總結(jié):

1. 反射Class對(duì)象, 反射Constructor對(duì)象, 反射類(lèi)實(shí)例對(duì)象 是3個(gè)不同的對(duì)象,如果剛開(kāi)始不熟悉API,建議分開(kāi)創(chuàng)建;

2.getConstructor() 和 getDeclaredConstructor(類(lèi)<?>... parameterTypes)方法的區(qū)別 前者是獲取public類(lèi)型構(gòu)造方法的Constructor對(duì)象,后者是獲取全類(lèi)型(public protect default private)類(lèi)型的構(gòu)造方法的Constructor對(duì)象

3.反射私有構(gòu)造方法的時(shí)候,一定要setAccessible(true),不然會(huì)報(bào)錯(cuò)java.lang.IllegalAccessException錯(cuò)誤 * true表示:禁止java語(yǔ)言使用時(shí)安全檢查,暴力訪問(wèn)

4. 調(diào)用Constructor類(lèi)中newInstance()這個(gè)方法時(shí),注意newInstance沒(méi)有帶參數(shù)(不帶參數(shù)可以不寫(xiě),或?qū)懗蒼ull 都可以行) 此方法內(nèi)部實(shí)際上調(diào)用了無(wú)參數(shù)構(gòu)造方法,必須保證無(wú)參構(gòu)造存在才可以,否則會(huì)拋出java.lang.InstantiationException異常。

3.3 反射調(diào)用類(lèi)中方法

方法名說(shuō)明
public Method[] getMethods()獲取所有"公有方法";(包含了父類(lèi)的方法也包含Object類(lèi))
public Method getMethod(String name,Class<?>... parameterTypes)獲取指定參數(shù)的公共成員方法 類(lèi)對(duì)象。
public Method[] getDeclaredMethods()獲取所有的成員方法,包括私有的(不包括繼承的)
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)獲取指定參數(shù)的方法對(duì)象
public Object invoke(Object obj,Object... args)在具有指定參數(shù)的 方法對(duì)象上調(diào)用此 方法對(duì)象表示的底層方法。

我們看看這個(gè)例子

package com.example.javademo.reflect;
public class MethodTest {
    public MethodTest() {
        System.out.println("調(diào)用  MethodTest默認(rèn)的共有構(gòu)造方法");
    }
    String fruit = "蘋(píng)果";
    int milliliter = 0;
    char game = 'X';
    String mood = "開(kāi)心";
    public void eat(String fruit) {
        this.fruit = fruit;
        System.out.println("調(diào)用public成員方法 eat  吃的水果為 :" + fruit);
    }
    int drink(int milliliter) {
        this.milliliter = milliliter;
        System.out.println("調(diào)用default成員方法 drink 喝水毫升量 :" + milliliter);
        return milliliter;
    }
    protected void play(char game) {
        this.game = game;
        System.out.println("調(diào)用protected成員方法 play 玩游戲 :" + game);
    }
    private String happy(String mood) {
        this.mood = mood;
        System.out.println("調(diào)用private成員方法 happy 今日心情:" + mood);
        return mood;
    }
}

反射測(cè)試類(lèi)

package com.example.javademo.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectMethod {
    public static void main(String[] args) {
        try {
            System.out.println("**********************獲取反射后類(lèi)對(duì)象*********************************");
            //獲取方法類(lèi)的class對(duì)象
            Class methodClass = Class.forName("com.example.javademo.reflect.MethodTest");
            System.out.println("反射類(lèi)對(duì)象 :" + methodClass);
            System.out.println("**********************獲取反射類(lèi)中所有的成員方法**************************");
            //返回一個(gè)"方法數(shù)組對(duì)象":反射類(lèi)或接口中所有聲明的方法,包括公共,保護(hù),默認(rèn)(包)訪問(wèn)和私有方法,但不包括繼承的方法。
            Method[] methods = methodClass.getDeclaredMethods();
            for (Method m : methods) {
                System.out.println(m);
            }
            System.out.println("***************第一種*******調(diào)用反射類(lèi)中public成員方法**************************");
            //返回一個(gè)方法對(duì)象,它表示此表示的類(lèi)或接口的指定聲明的方法對(duì)象。
            //第一個(gè)參數(shù)為方法名,第二個(gè)可變參數(shù) : 為該方法傳入的參數(shù)
            Method methodPublic = methodClass.getDeclaredMethod("eat", String.class);
            //PUBLIC :1     PRIVATE:2    PROTECTED:4   PACKAGE(default):8
            System.out.println("打印該public方法的修飾符 :" + methodPublic.getModifiers());
            System.out.println("打印該public方法對(duì)象 表示方法的名稱: "+methodPublic.getName());
            System.out.println("打印該public方法對(duì)象 可執(zhí)行文件的形式參數(shù)的數(shù)量 :" + methodPublic.getParameterCount());
            //實(shí)例化一個(gè)MethodTest類(lèi)對(duì)象,每個(gè)類(lèi)有一個(gè)默認(rèn)的無(wú)參構(gòu)造方法,可以寫(xiě)或不寫(xiě)
            //但是如果類(lèi)中有帶參數(shù)的構(gòu)造方法,那無(wú)參構(gòu)造方法是必須要寫(xiě)出來(lái)的,不然new對(duì)象的時(shí)候,就會(huì)報(bào)錯(cuò)
            MethodTest objMethodTest = (MethodTest)methodClass.getDeclaredConstructor().newInstance();
            System.out.println("MethodTest類(lèi)對(duì)象 :" + objMethodTest);
            //invoke方法 第一個(gè)參數(shù): 從底層方法被調(diào)用的對(duì)象   如果底層方法是靜態(tài)的,則第一個(gè)參數(shù)obj對(duì)象傳遞null。
            //第二個(gè)參數(shù): 該方法調(diào)用的參數(shù)
            //如果方法正常完成,則返回的值將返回給調(diào)用者.
            Object objectreturn1 = methodPublic.invoke(objMethodTest, "菠蘿");
            //eat方法返回值為 null
            System.out.println("eat方法 返回值為 :" + objectreturn1);
            System.out.println("***************第二種*******調(diào)用反射類(lèi)中private成員方法**************************");
            Method methodPrivate = methodClass.getDeclaredMethod("happy", String.class);
            System.out.println("打印該private方法的修飾符 :" + methodPrivate.getModifiers());
            System.out.println("打印該private方法對(duì)象 表示方法的名稱: "+methodPrivate.getName());
            System.out.println("打印該public方法對(duì)象 可執(zhí)行文件的形式參數(shù)的數(shù)量 :" + methodPrivate.getParameterCount());
            //如果是訪問(wèn)私有方法,則要加上這句話,禁止java語(yǔ)言使用時(shí)安全檢查
            methodPrivate.setAccessible(true);
            Object objectreturn2 = methodPrivate.invoke(objMethodTest, "超級(jí)nice");
            System.out.println("happy方法 返回值為:"+objectreturn2);
            System.out.println("***************第三種*******調(diào)用反射類(lèi)中protected成員方法**************************");
            Method methodProtected = methodClass.getDeclaredMethod("play", char.class);
            System.out.println("打印該protected方法的修飾符 :" + methodProtected.getModifiers());
            System.out.println("打印該protected方法對(duì)象 表示方法的名稱: "+methodProtected.getName());
            System.out.println("打印該protected方法對(duì)象 可執(zhí)行文件的形式參數(shù)的數(shù)量 :" + methodProtected.getParameterCount());
            Object objectreturn3 = methodProtected.invoke(objMethodTest, 'Y');
            System.out.println("play方法 返回值為:"+objectreturn3);
            System.out.println("***************第四種*******調(diào)用反射類(lèi)中default成員方法**************************");
            Method methodDefault = methodClass.getDeclaredMethod("drink", int.class);
            System.out.println("打印該protected方法的修飾符 :" + methodDefault.getModifiers());
            System.out.println("打印該protected方法對(duì)象 表示方法的名稱: "+methodDefault.getName());
            System.out.println("打印該protected方法對(duì)象 可執(zhí)行文件的形式參數(shù)的數(shù)量 :" + methodDefault.getParameterCount());
            Object objectreturn4 = methodDefault.invoke(objMethodTest, 180);
            System.out.println("drink方法 返回值為:"+objectreturn4);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

打印log:

**********************獲取反射后類(lèi)對(duì)象*********************************
反射類(lèi)對(duì)象 :class com.example.javademo.reflect.MethodTest
**********************獲取反射類(lèi)中所有的成員方法**************************
public void com.example.javademo.reflect.MethodTest.eat(java.lang.String)
private java.lang.String com.example.javademo.reflect.MethodTest.happy(java.lang.String)
protected void com.example.javademo.reflect.MethodTest.play(char)
int com.example.javademo.reflect.MethodTest.drink(int)
***************第一種*******調(diào)用反射類(lèi)中public成員方法**************************
打印該public方法的修飾符 :1
打印該public方法對(duì)象 表示方法的名稱: eat
打印該public方法對(duì)象 可執(zhí)行文件的形式參數(shù)的數(shù)量 :1
調(diào)用  MethodTest默認(rèn)的共有構(gòu)造方法
MethodTest類(lèi)對(duì)象 :com.example.javademo.reflect.MethodTest@15db9742
調(diào)用public成員方法 eat  吃的水果為 :菠蘿
eat方法 返回值為 :null
***************第二種*******調(diào)用反射類(lèi)中private成員方法**************************
打印該private方法的修飾符 :2
打印該private方法對(duì)象 表示方法的名稱: happy
打印該public方法對(duì)象 可執(zhí)行文件的形式參數(shù)的數(shù)量 :1
調(diào)用private成員方法 happy 今日心情:超級(jí)nice
happy方法 返回值為:超級(jí)nice
***************第三種*******調(diào)用反射類(lèi)中protected成員方法**************************
打印該protected方法的修飾符 :4
打印該protected方法對(duì)象 表示方法的名稱: play
打印該protected方法對(duì)象 可執(zhí)行文件的形式參數(shù)的數(shù)量 :1
調(diào)用protected成員方法 play 玩游戲 :Y
play方法 返回值為:null
***************第四種*******調(diào)用反射類(lèi)中default成員方法**************************
打印該protected方法的修飾符 :0
打印該protected方法對(duì)象 表示方法的名稱: drink
打印該protected方法對(duì)象 可執(zhí)行文件的形式參數(shù)的數(shù)量 :1
調(diào)用default成員方法 drink 喝水毫升量 :180
drink方法 返回值為:180

代碼中基本都做了注釋,通過(guò)上面的例子,總結(jié):

1. 反射class對(duì)象, 反射Method對(duì)象 反射類(lèi)實(shí)例對(duì)象 是3個(gè)不同的對(duì)象,要區(qū)分開(kāi)

2. 在反射調(diào)用private方法時(shí),一定要禁止java語(yǔ)言使用時(shí)安全檢查,要setAccessible(true),其他修飾符方法可以不用加這句話

3. (反射Method對(duì)象).invoke(Object obj, Object ...args) 方法參數(shù)的理解 :

1. 第一個(gè)參數(shù)為 通過(guò)用反射方法構(gòu)造出來(lái)的 反射類(lèi)實(shí)例對(duì)象

2. 第二個(gè)可變參數(shù)為: 該方法需要傳入的參數(shù)

3. 如果方法正常完成,則將返回值返回

3.4 反射類(lèi)中的成員變量

方法說(shuō)明
Field[] getFields()獲取所有的"公有字段"
public Field getField(String fieldName)獲取指定參數(shù)的共有字段
.Field[] getDeclaredFields()獲取所有字段,包括:私有、受保護(hù)、默認(rèn)、公有;
public Field getDeclaredField(String fieldName)獲取某個(gè)字段(包括私有的)
set(Object obj, Object value)將指定Field對(duì)象  設(shè)置為指定的新值

我們通過(guò)Demo講解:

package com.example.javademo.reflect;
/**
 * desc   : 供反射調(diào)用的FieldTest類(lèi)
 * version: 1.0
 */
public class FieldTest {
    public FieldTest() {
        System.out.println("調(diào)用FieldTest 默認(rèn)無(wú)參構(gòu)造方法");
    }
    public int age = 18;
    private String name = "張三";
    String sex = "男";
    protected String phoneNum = "123456789";
    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    public String getSex() {
        return sex;
    }
    public String getPhoneNum() {
        return phoneNum;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }
    @Override
    public String toString() {
        return "FieldTest{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", phoneNum='" + phoneNum + '\'' +
                '}';
    }

反射測(cè)試類(lèi):

package com.example.javademo.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * desc   : 反射FiledTest類(lèi)中各字段(Field)的實(shí)現(xiàn)類(lèi)
 * version: 1.0
 */
public class ReflectField {
    public static void main(String[] args) {
        //用正常的new對(duì)象的方式,給字段賦值,打印對(duì)象值, 測(cè)試用
       /* FieldTest objcetFieldTest = new FieldTest();
        objcetFieldTest.setAge(15);
        objcetFieldTest.setName("xiaomao");
        objcetFieldTest.setPhoneNum("12345678");
        objcetFieldTest.setSex("男");
        System.out.println(objcetFieldTest.toString());*/
        //通過(guò)反射的方式,修改字段值
        try {
            //通過(guò)反射獲取Class對(duì)象
            Class FieldTestClass = Class.forName("com.example.javademo.reflect.FieldTest");
            //用反射的方式來(lái)修改字段(成員變量)的值
            System.out.println("************獲取所有的字段(包括共有、私有、受保護(hù)、默認(rèn)的)********************");
            Field[] fields = FieldTestClass.getDeclaredFields();
            for (Field f : fields) {
                System.out.println(f);
            }
            //用反射的方式來(lái)構(gòu)造FieldTestl類(lèi)對(duì)象
            FieldTest objFieldTest = (FieldTest) FieldTestClass.getDeclaredConstructor().newInstance();
            System.out.println("*************反射獲取public字段并調(diào)用***********************************");
            //返回一個(gè) Field對(duì)象,它表示的類(lèi)或接口的指定已聲明字段對(duì)象。
            Field fieldPublic =  FieldTestClass.getDeclaredField("age");
            System.out.println("該字段的修飾符 :" + fieldPublic.getModifiers());
            System.out.println("該字段的名稱 :" + fieldPublic.getName());
            /*
            * 獲取字段的值:有 getInt(Object obj) getLong(Object obj) get(Object obj)等方法
            *
            * obj :為通過(guò)反射方法 構(gòu)造出來(lái)的類(lèi)對(duì)象
            * */
            //獲取int類(lèi)型 實(shí)例字段的默認(rèn)值
            System.out.println("通過(guò)反射方式獲取age默認(rèn)值 : " + fieldPublic.getInt(objFieldTest));
           /* 設(shè)置字段的值:
 		    Field  public void set(Object obj,Object value):
 			參數(shù)說(shuō)明:
				1.obj: 通過(guò)反射方法 構(gòu)造出來(lái)的類(lèi)對(duì)象
 				2.value:要為字段設(shè)置的值;
 		   */
            fieldPublic.set(objFieldTest, 20);
            //通過(guò)反射的方式調(diào)用 getAge() 方法
            Method method = FieldTestClass.getDeclaredMethod("getAge");
            Object objectReturn =  method.invoke(objFieldTest);
            System.out.println("通過(guò)反射方式set新值之后, age的值 :" + objectReturn);
            System.out.println("*************反射獲取private字段并調(diào)用***********************************");
            //在項(xiàng)目實(shí)際中,因?yàn)樗接凶兞亢头椒?,無(wú)法在外部類(lèi)去調(diào)用它們,所以反射在這點(diǎn)上就派上用場(chǎng)了
            Field fieldPrivate = FieldTestClass.getDeclaredField("name");
            //private字段一定要調(diào)用setAccessible(true)  禁止java語(yǔ)言使用時(shí)安全檢查
            fieldPrivate.setAccessible(true);
            System.out.println("通過(guò)反射方式獲取age默認(rèn)值 : " + fieldPrivate.get(objFieldTest));
            //修改private變量name的值
            fieldPrivate.set(objFieldTest, "李四");
            //通過(guò)反射的方式調(diào)用 getName() 方法
            Method objectMethod = FieldTestClass.getDeclaredMethod("getName");
            Object objectReturn1 =  objectMethod.invoke(objFieldTest);
            System.out.println("通過(guò)反射方式set新值之后, name的值 :" + objectReturn1);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

打印log:

************獲取所有的字段(包括共有、私有、受保護(hù)、默認(rèn)的)********************
public int com.example.javademo.reflect.FieldTest.age
private java.lang.String com.example.javademo.reflect.FieldTest.name
java.lang.String com.example.javademo.reflect.FieldTest.sex
protected java.lang.String com.example.javademo.reflect.FieldTest.phoneNum
調(diào)用FieldTest 默認(rèn)無(wú)參構(gòu)造方法
*************反射獲取public字段并調(diào)用***********************************
該字段的修飾符 :1
該字段的名稱 :age
通過(guò)反射方式獲取age默認(rèn)值 : 18
通過(guò)反射方式set新值之后, age的值 :20
*************反射獲取private字段并調(diào)用***********************************
通過(guò)反射方式獲取age默認(rèn)值 : 張三
通過(guò)反射方式set新值之后, name的值 :李四

通過(guò)例子,總結(jié)如下:

1. 反射class對(duì)象, 反射Field對(duì)象 反射類(lèi)實(shí)例對(duì)象 是3個(gè)不同的對(duì)象,要區(qū)分開(kāi)

2.在反射調(diào)用private字段時(shí),一定要禁止java語(yǔ)言使用時(shí)安全檢查,要setAccessible(true)

3. Field public void set(Object obj,Object value):

參數(shù)說(shuō)明:

1.obj: 通過(guò)反射方法 構(gòu)造出來(lái)的類(lèi)對(duì)象

2.value:要為字段設(shè)置的值;

3.5 反射類(lèi)中靜態(tài)方法和變量

怎么修改static修飾的變量呢?靜態(tài)變量和方法是在類(lèi)的實(shí)例化之前就進(jìn)行了初始化(類(lèi)的初始化階段),靜態(tài)變量和方法是從屬于類(lèi)本身的,跟new出來(lái)的具體對(duì)象無(wú)關(guān),所以我們獲取變量就不需要傳入對(duì)象,直接傳入null即可。

Demo如下:

package com.example.javademo.reflect;
public class StaticFieldTest {
    public StaticFieldTest() {
        System.out.println("調(diào)用 StaticFieldTest 無(wú)參構(gòu)造方法");
    }
    //靜態(tài)變量
    public static int age = 15;
    public static void setAge(int age) {
        StaticFieldTest.age = age;
    }
    //靜態(tài)方法
    public static int getAge() {
        return age;
    }
}

反射測(cè)試類(lèi):

package com.example.javademo.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectStatic {
    public static void main(String[] args) {
        try {
            //獲取 StaticFieldTest  class對(duì)象
            Class staticClazz = Class.forName("com.example.javademo.reflect.StaticFieldTest");
            //獲取靜態(tài)Field對(duì)象
            Field staticField = staticClazz.getDeclaredField("age");
            //因?yàn)槭莗ulic修飾符,這句話也可以不用寫(xiě)
            staticField.setAccessible(true);
            //通過(guò)set方法,修改值,  靜態(tài)變量 是從屬于類(lèi),可以不用傳入類(lèi)實(shí)例對(duì)象,直接傳入null
            staticField.set(null, 25);
            //驗(yàn)證修改后的值
            Method agetet = staticClazz.getDeclaredMethod("getAge");
            // 靜態(tài)方法 是從屬于類(lèi), 可以不用傳入類(lèi)實(shí)例對(duì)象,直接傳入null
            int agetest = (int) agetet.invoke(null);
            System.out.println("**********************打印修改后的age值**************************");
            System.out.println(agetest);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

打印結(jié)果:

**********************打印修改后的age值**************************
25

總結(jié)如下:

1. 對(duì)于static 變量和方法,因?yàn)樗菑膶儆陬?lèi)本身,在類(lèi)的實(shí)例化之前就進(jìn)行了初始化,當(dāng)傳入obj對(duì)象參數(shù)的時(shí)候,直接傳入null即可。

4. 反射在Android中的應(yīng)用

4.1反射實(shí)現(xiàn)獲取頂層activity的名稱

如前言背景中的問(wèn)題描述,有了上面的理論知識(shí)做為基礎(chǔ),實(shí)現(xiàn)代碼如下:

 /**
     * @description: 通過(guò)反射方式獲取 頂層activity名稱
     * @param: null
     * @return: boolean 如果是目標(biāo)activity 則返回true
    */
    public boolean isTopTargetActivity() {
        try {
            //通過(guò)包名和類(lèi)名反射獲取 class 對(duì)象
            Class activityThreadClass = Class.forName("android.app.ActivityThread");
            //第二種: 反射創(chuàng)建 activiyThread對(duì)象  反射調(diào)用靜態(tài)方法,第一個(gè)參數(shù)obj對(duì)象傳遞 null
            Object activityThreadObj = activityThreadClass.getMethod("currentActivityThread").invoke(null);
            Log.e("test", "====activityThreadObj: "+activityThreadObj);
            //獲取 mActivities Field對(duì)象  final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
            Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
            //禁止Java語(yǔ)言訪問(wèn)使用時(shí)進(jìn)行檢查
            activitiesField.setAccessible(true);
            //返回該所表示的字段的值 Field
            Map activities = (Map) activitiesField.get(activityThreadObj);
            for (Object activityClientRecord : activities.values()) {
                //獲取 ActivityClientRecord class對(duì)象
                Class activityRecordClass = activityClientRecord.getClass();
                //獲取 boolean paused 字段 對(duì)象
                Field pausedField = activityRecordClass.getDeclaredField("paused");
                //允許暴力訪問(wèn),禁止java語(yǔ)言運(yùn)行時(shí)安全檢查
                pausedField.setAccessible(true);
                //Activity onResume的判斷條件
                if (!pausedField.getBoolean(activityClientRecord)) {
                    //獲取 Activity activity field對(duì)象
                    Field activityField = activityRecordClass.getDeclaredField("activity");
                    activityField.setAccessible(true);
                    //獲取當(dāng)前顯示的activity的對(duì)象
                    Activity activity = (Activity) activityField.get(activityClientRecord);
                    //獲取當(dāng)前activity的名稱
                    String className = activity.getClass().toString();
                    Log.e("test", "====通過(guò)反射獲取的className===="+className);
                    if ("cn.com.test.activity.MainActivity".equals(className)) {
                        return true;
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            Log.e("test", "======ClassNotFoundException===="+e.getMessage());
        } catch (InvocationTargetException e) {
            Log.e("test", "======InvocationTargetException===="+e.getMessage());
        } catch (NoSuchMethodException e) {
            Log.e("test", "======NoSuchMethodException===="+e.getMessage());
        } catch (NoSuchFieldException e) {
            Log.e("test", "======NoSuchFieldException===="+e.getMessage());
        } catch (IllegalAccessException e) {
            Log.e("test", "======IllegalAccessException===="+e.getMessage());
        }
        return false;
    }

4.2 反射調(diào)用SystemProperties中set get方法

再者,比如第三方應(yīng)用是無(wú)法直接調(diào)用SystemProperties中 get set 方法,我們也可以通過(guò)反射來(lái)實(shí)現(xiàn), 這個(gè)工具類(lèi)已經(jīng)實(shí)現(xiàn)好,可以拿去直接用:

public class SystemPropertiesUtils {
    private static final String TAG = "SystemPropertiesUtils";
    private static Class<?> mClassType = null;
    private static Method mGetMethod = null;
    private static Method mGetIntMethod = null;
    private static Method mGetBooleanMethod = null;
    private static Class<?> getSystemPropertiesClass() throws ClassNotFoundException {
        if (mClassType == null) {
            mClassType = Class.forName("android.os.SystemProperties");
        }
        return mClassType;
    }
    private static Method getMethod() throws Exception {
        if (mGetMethod == null) {
            Class clazz = getSystemPropertiesClass();
            mGetMethod = clazz.getDeclaredMethod("get", String.class);
        }
        return mGetMethod;
    }
    private static Method getIntMethod() throws Exception {
        if (mGetIntMethod == null) {
            Class clazz = getSystemPropertiesClass();
            mGetIntMethod = clazz.getDeclaredMethod("getInt", String.class, int.class);
        }
        return mGetIntMethod;
    }
    private static Method getBooleanMethod() throws Exception {
        if (mGetBooleanMethod == null) {
            Class clazz = getSystemPropertiesClass();
            mGetBooleanMethod = clazz.getDeclaredMethod("getBoolean", String.class, boolean.class);
        }
        return mGetBooleanMethod;
    }
    public static String get(String key, String def) {
        try {
            String value = (String) getMethod().invoke(null, key);
            if (!TextUtils.isEmpty(value)) {
                return value;
            }
        } catch (Exception e) {
            Log.d(TAG, "Unable to read system properties");
        }
        return def;
    }
    public static int getInt(String key, int def) {
        int value = def;
        try {
            value = (int) getIntMethod().invoke(null, key, def);
        } catch (Exception e) {
            Log.d(TAG, "Unable to read system properties");
        }
        return value;
    }
    public static boolean getBoolean(String key, boolean def) {
        boolean value = def;
        try {
            value = (Boolean) getBooleanMethod().invoke(null, key, def);
        } catch (Exception e) {
            Log.d(TAG, "Unable to read system properties");
        }
        return value;
    }
}

4.3 通過(guò)反射創(chuàng)建Bitmap縮略圖

public static Bitmap createVideoThumbnail(String filePath) {
        // MediaMetadataRetriever is available on API Level 8
        // but is hidden until API Level 10
        Class<?> clazz = null;
        Object instance = null;
        try {
            clazz = Class.forName("android.media.MediaMetadataRetriever");
            instance = clazz.newInstance();
 
            Method method = clazz.getMethod("setDataSource", String.class);
            method.invoke(instance, filePath);
 
            // The method name changes between API Level 9 and 10.
            if (Build.VERSION.SDK_INT <= 9) {
                return (Bitmap) clazz.getMethod("captureFrame").invoke(instance);
            } else {
                byte[] data = (byte[]) clazz.getMethod("getEmbeddedPicture").invoke(instance);
                if (data != null) {
                    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    if (bitmap != null) return bitmap;
                }
                return (Bitmap) clazz.getMethod("getFrameAtTime").invoke(instance);
            }
        } catch (IllegalArgumentException ex) {
            // Assume this is a corrupt video file
        } catch (RuntimeException ex) {
            // Assume this is a corrupt video file.
        } catch (InstantiationException e) {
            Log.e(TAG, "createVideoThumbnail", e);
        } catch (InvocationTargetException e) {
            Log.e(TAG, "createVideoThumbnail", e);
        } catch (ClassNotFoundException e) {
            Log.e(TAG, "createVideoThumbnail", e);
        } catch (NoSuchMethodException e) {
            Log.e(TAG, "createVideoThumbnail", e);
        } catch (IllegalAccessException e) {
            Log.e(TAG, "createVideoThumbnail", e);
        } finally {
            try {
                if (instance != null) {
                    clazz.getMethod("release").invoke(instance);
                }
            } catch (Exception ignored) {
            }
        }
        return null;
    }

MediaMetadataRetriever.java 類(lèi)中有個(gè)public無(wú)參構(gòu)造方法, 可以通過(guò)反射方式clazz.getDeclaredConstructor().newInstance() 拿到這個(gè) 類(lèi)對(duì)象

接下來(lái),就是獲取Method Field 對(duì)象 再通過(guò)invoke set 方法去修改方法 變量的值。

5. 總結(jié)

反射在Andorid中開(kāi)發(fā)應(yīng)用的比較多,Class對(duì)象, Constructor 對(duì)象,Method 對(duì)象 Field對(duì)象各自的常用API要理解并熟練運(yùn)用, 結(jié)合源碼多閱讀多仿寫(xiě),相信你也可以carry住反射。

到此這篇關(guān)于詳解Andorid開(kāi)發(fā)中反射機(jī)制是怎么一回事的文章就介紹到這了,更多相關(guān)Andorid反射機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • Android中Fragment的基本用法示例總結(jié)

    Android中Fragment的基本用法示例總結(jié)

    Fragment是activity的界面中的一部分或一種行為,下面這篇文章主要給大家介紹了關(guān)于Android中Fragment的基本用法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-05-05
  • Android 無(wú)障礙全局懸浮窗實(shí)現(xiàn)示例

    Android 無(wú)障礙全局懸浮窗實(shí)現(xiàn)示例

    本文主要介紹了Android 無(wú)障礙全局懸浮窗實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Flutter 日期時(shí)間DatePicker控件及國(guó)際化

    Flutter 日期時(shí)間DatePicker控件及國(guó)際化

    這篇文章主要介紹了Flutter 日期時(shí)間DatePicker控件及國(guó)際化,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Android使用TypeFace設(shè)置TextView的文字字體

    Android使用TypeFace設(shè)置TextView的文字字體

    這篇文章主要介紹了Android使用TypeFace設(shè)置TextView的文字字體的方法,幫助大家更好的利用Android開(kāi)發(fā),感興趣的朋友可以了解下
    2021-01-01
  • 詳解Android_性能優(yōu)化之ViewPager加載成百上千高清大圖oom解決方案

    詳解Android_性能優(yōu)化之ViewPager加載成百上千高清大圖oom解決方案

    這篇文章主要介紹了詳解Android_性能優(yōu)化之ViewPager加載成百上千高清大圖oom解決方案,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • Android自定義廣播接收

    Android自定義廣播接收

    這篇文章主要為大家詳細(xì)介紹了Android自定義廣播接收,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Android自定義簡(jiǎn)單的頂部標(biāo)題欄

    Android自定義簡(jiǎn)單的頂部標(biāo)題欄

    這篇文章主要為大家詳細(xì)介紹了Android自定義簡(jiǎn)單的頂部標(biāo)題欄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Android應(yīng)用內(nèi)懸浮窗的實(shí)現(xiàn)方案示例

    Android應(yīng)用內(nèi)懸浮窗的實(shí)現(xiàn)方案示例

    本篇文章主要介紹了Android應(yīng)用內(nèi)懸浮窗的實(shí)現(xiàn)方案示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • Android  view自定義實(shí)現(xiàn)動(dòng)態(tài)進(jìn)度條

    Android view自定義實(shí)現(xiàn)動(dòng)態(tài)進(jìn)度條

    這篇文章主要介紹了Android view自定義實(shí)現(xiàn)動(dòng)態(tài)進(jìn)度條的相關(guān)資料,這里提供實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下
    2016-12-12
  • Android 中TextView中跑馬燈效果的實(shí)現(xiàn)方法

    Android 中TextView中跑馬燈效果的實(shí)現(xiàn)方法

    這篇文章主要介紹了Android 中TextView中跑馬燈效果的實(shí)現(xiàn)方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02

最新評(píng)論