Unity C#基礎(chǔ)之 反射反射丁侄,程序員的快樂

反射反射义起,程序員的快樂

這句話想必大家都經(jīng)常聽過滴须,基本上在絕大多數(shù)的框架和一些設(shè)計(jì)模式中都能看到反射的身影(MVC馏艾、IOC诊杆、AOP蝗锥、O/RM)妓灌, 反射:是.Net Framework提供的一個(gè)幫助類庫轨蛤,可以訪問dll的metadata,并且使用它祥山。

反射給我們帶來的優(yōu)缺點(diǎn)如下:
  • 極大的解耦
  • 動態(tài)創(chuàng)建
  • 代碼多編寫量大
  • 避開編譯器的檢查
  • 性能問題
    • 反射性能要差普通的400+倍
    • 但是絕對值小,幾乎不影響項(xiàng)目性能
    • 而且還可以優(yōu)化掉伏,空間換時(shí)間(非常適合泛型緩存)

下面一些示例介紹一些反射比較實(shí)用的基本用法 (Unity版本:2017.3.0 P4 .NET 4.6)

示例工程下載

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

public class InvokeReflection : MonoBehaviour
{
    void Start()
    {
        Learn00();
    }


    public void Learn00()
    {
        /*
         *System.Reflection.Assembly類有兩個(gè)靜態(tài)方法:Assembly.Load(string assemblyname)和Assembly.LoadFrom(string filename) 缝呕。
         * 通常用這兩個(gè)方法把程序集加載到應(yīng)用程序域中澳窑。 如果你希望加載的程序集超出了CLR的預(yù)定探查范圍,你可以用 Assembly.LoadFrom直接從一個(gè)文件位置加載程序集供常。
         * Assembly.LoadFrom()和Assembly.LoadFile()摊聋,兩者的主要區(qū)別有兩點(diǎn):
         * 一:Assembly.LoadFile()只載入指定的dll文件,而不會自動加載相關(guān)的dll文件栈暇。如果下文例子使用Assembly.LoadFile()加載SayHello.dll麻裁,那么程序就只會加載
         * SayHello.dll而不會去加載SayHello.dll引用的BaseClass.dll文件。
         *二:用Assembly.LoadFrom()載入一個(gè)Assembly時(shí)源祈,會先檢查前面是否已經(jīng)載入過相同名字的Assembly煎源;
         * 而Assembly.LoadFile()則不會做類似的檢查。
         */
        //C:\Users\Administrator\Desktop\New Unity Project\Assets\DLL
        Assembly assemly2 = Assembly.LoadFrom(@"C:\Users\Administrator\Desktop\New Unity Project\Assets\Scripts\TestReflection.dll");
        Assembly assemly1 = Assembly.LoadFile(@"C:\Users\Administrator\Desktop\New Unity Project\Assets\Scripts\TestReflection.dll");
        Assembly assemly = Assembly.Load("TestReflection");//1填加DLL
        Type testType = assemly.GetType("HaiLan.TestReflection.TestReflectionDLL");//2獲取對應(yīng)的類信息香缺,需要填加對應(yīng)的命名空間
        object oTestReflectionDLL = Activator.CreateInstance(testType);//3 創(chuàng)建對象
        IReflectionDLL iTestReflectionDLL = oTestReflectionDLL as IReflectionDLL;//4 類型轉(zhuǎn)換
        iTestReflectionDLL.TestShow1();//5 方法調(diào)用

        foreach (var item in assemly.GetModules())
        {
            Debug.Log(item.Name);//打印結(jié)果 TestReflection.dll
        }
        foreach (var type in assemly.GetTypes())
        {
            Debug.Log(type.Name);
            foreach (var item in type.GetMethods())
            {
                Debug.Log(item.Name);
            }
        }
    }
}

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

    public void Learn01()
    {
        Console.WriteLine("************************Reflection*****************");
        Assembly assemly = Assembly.Load("TestReflection");

        Type testType = assemly.GetType("HaiLan.TestReflection.TestReflectionDLL");
        object oTest1 = Activator.CreateInstance(testType);
        object oTest2 = Activator.CreateInstance(testType, new object[] { });
        object oTest3 = Activator.CreateInstance(testType, new object[] { 9257 });
        object oTest4 = Activator.CreateInstance(testType, new object[] { "海瀾" });

        Type genericType = assemly.GetType("HaiLan.TestReflection.GenericClass`3");//泛型類還有3個(gè)未指定的類型
        Type genericNewType = genericType.MakeGenericType(typeof(int), typeof(string), typeof(InvokeReflection));
        object oGeneric = Activator.CreateInstance(genericNewType);
        GenericClass<int,string, InvokeReflection> TempGenericClass = oGeneric as GenericClass<int, string, InvokeReflection>;
        TempGenericClass.Show(9257,"海瀾", this);

        Type singletonType = assemly.GetType("HaiLan.TestReflection.Singleton");
        object oSingleton1 = Activator.CreateInstance(singletonType, true);//單例模型依然可以創(chuàng)建新類
        object oSingleton2 = Activator.CreateInstance(singletonType, true);
        object oSingleton3 = Activator.CreateInstance(singletonType, true);
    }

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

    public void Learn02()
    {
        Assembly assemly = Assembly.Load("TestReflection");
        Type testType = assemly.GetType("HaiLan.TestReflection.ReflectionTest");
        object oTest = Activator.CreateInstance(testType);
        {
            MethodInfo method = testType.GetMethod("Show1");//以前寫的具體方法手销,換成字符串
            method.Invoke(oTest, null);
        }
        {
            MethodInfo method = testType.GetMethod("Show2");//帶參數(shù)
            method.Invoke(oTest, new object[] { 9257 });
        }
        {
            MethodInfo method = testType.GetMethod("Show5");//靜態(tài)
            method.Invoke(oTest, new object[] { "海瀾" });
            method.Invoke(null, new object[] { "海瀾" });
        }
        {
            MethodInfo method = testType.GetMethod("Show3", new Type[] { });//重載方法
            method.Invoke(oTest, new object[] { });
        }
        {
            MethodInfo method = testType.GetMethod("Show3", new Type[] { typeof(int) });//重載方法
            method.Invoke(oTest, new object[] { 9257 });
        }
        {
            MethodInfo method = testType.GetMethod("Show3", new Type[] { typeof(string) });//重載方法
            method.Invoke(oTest, new object[] { "海瀾" });
        }
        {
            MethodInfo method = testType.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });//重載方法
            method.Invoke(oTest, new object[] { 9257, "海瀾" });
        }
        {
            MethodInfo method = testType.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });//重載方法
            method.Invoke(oTest, new object[] { "海瀾", 9257 });
        }
        {
            MethodInfo method = testType.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);//私有方法
            method.Invoke(oTest, new object[] { "海瀾" });
        }
        {
            Type genericType = assemly.GetType("HaiLan.TestReflection.GenericMethod");
            object oGeneric = Activator.CreateInstance(genericType);
            MethodInfo method = genericType.GetMethod("Show");
            //MethodInfo method = genericType.GetMethod("Show`3");//錯(cuò)誤寫法,應(yīng)為在編譯期間就是無法通過的
            MethodInfo methodNew = method.MakeGenericMethod(typeof(int), typeof(string), typeof(int));
            methodNew.Invoke(oGeneric, new object[] { 9257, "海瀾", 92570 });
        }
    }

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

    public void Learn03()
    {
        {
            People people = new People();
            people.Id = 9257;
            people.Name = "海瀾";
            people.Description = "菜鳥海瀾";

            Debug.Log($"people.Id={people.Id}");
            Debug.Log($"people.Name={people.Name}");
            Debug.Log($"people.Description={people.Description}");
        }
        {
            Type type = typeof(People);
            object oPeople = Activator.CreateInstance(type);
            foreach (var item in type.GetProperties())//反射可以給對象的屬性 動態(tài) 賦值/獲取值图张,
            {
                Debug.Log(item.Name);
                Debug.Log(item.GetValue(oPeople));
                if (item.Name.Equals("Id"))
                {
                    item.SetValue(oPeople, 1235);
                }
                else if (item.Name.Equals("Name"))
                {
                    item.SetValue(oPeople, "菜鳥海瀾");
                }
                Debug.Log(item.GetValue(oPeople));
            }
            foreach (var item in type.GetFields())//反射可以給對象的字段  動態(tài) 賦值/獲取值锋拖,
            {
                Debug.Log(item.Name);
                Debug.Log(item.GetValue(oPeople));
                if (item.Name.Equals("Description"))
                    item.SetValue(oPeople, "菜鳥海瀾,ID:9257");
                Debug.Log(item.GetValue(oPeople));
            }

        }
    }

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

反射介紹如下:

反射是.NET中的重要機(jī)制埂淮,通過反射姑隅,可以在運(yùn)行時(shí)獲得程序或程序集中每一個(gè)類型(包括類、結(jié)構(gòu)倔撞、委托讲仰、接口和枚舉等)的成員和成員的信息。有了反射痪蝇,即可對每一個(gè)類型了如指掌鄙陡。另外我還可以直接創(chuàng)建對象,即使這個(gè)對象的類型在編譯時(shí)還不知道躏啰。

反射的用途:

  • 使用Assembly定義和加載程序集趁矾,加載在程序集清單中列出模塊,以及從此程序集中查找類型并創(chuàng)建該類型的實(shí)例给僵。
  • 使用Module了解包含模塊的程序集以及模塊中的類等毫捣,還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。
  • 使用ConstructorInfo了解構(gòu)造函數(shù)的名稱帝际、參數(shù)蔓同、訪問修飾符(如pulic 或private)和實(shí)現(xiàn)詳細(xì)信息(如abstract或virtual)等。
  • 使用MethodInfo了解方法的名稱蹲诀、返回類型斑粱、參數(shù)、訪問修飾符(如pulic 或private)和實(shí)現(xiàn)詳細(xì)信息(如abstract或virtual)等脯爪。
  • 使用FiedInfo了解字段的名稱则北、訪問修飾符(如public或private)和實(shí)現(xiàn)詳細(xì)信息(如static)等矿微,并獲取或設(shè)置字段值。
  • 使用EventInfo了解事件的名稱尚揣、事件處理程序數(shù)據(jù)類型涌矢、自定義屬性、聲明類型和反射類型等惑艇,添加或移除事件處理程序蒿辙。
  • 使用PropertyInfo了解屬性的名稱、數(shù)據(jù)類型滨巴、聲明類型、反射類型和只讀或可寫狀態(tài)等俺叭,獲取或設(shè)置屬性值恭取。
  • 使用ParameterInfo了解參數(shù)的名稱、數(shù)據(jù)類型熄守、是輸入?yún)?shù)還是輸出參數(shù)蜈垮,以及參數(shù)在方法簽名中的位置等。

反射用到的命名空間:

    System.Reflection
    System.Type
    System.Reflection.Assembly

反射用到的主要類:

    System.Type 類--通過這個(gè)類可以訪問任何給定數(shù)據(jù)類型的信息裕照。
    System.Reflection.Assembly類--它可以用于訪問給定程序集的信息攒发,或者把這個(gè)程序集加載到程序中。

System.Type類:

System.Type 類對于反射起著核心的作用晋南。但它是一個(gè)抽象的基類惠猿,Type有與每種數(shù)據(jù)類型對應(yīng)的派生
類,我們使用這個(gè)派生類的對象的方法负间、字段偶妖、屬性來查找有關(guān)該類型的所有信息。

獲取給定類型的Type引用有3種常用方式:

    ● 使用 C# typeof 運(yùn)算符政溃。
        Type t = typeof(string);
    ● 使用對象GetType()方法趾访。
        string s = "grayworm";
        Type t = s.GetType(); 
    ● 還可以調(diào)用Type類的靜態(tài)方法GetType()。
        Type t = Type.GetType("System.String");
       
    上面這三類代碼都是獲取string類型的Type董虱,在取出string類型的Type引用t后扼鞋,我們就可以通過t來探測string類型的結(jié)構(gòu)了。 
    string n = "grayworm";
    Type t = n.GetType();
     foreach (MemberInfo mi in t.GetMembers())
     {
       Console.WriteLine("{0}/t{1}",mi.MemberType,mi.Name);
     }
    Type類的屬性:
        Name 數(shù)據(jù)類型名
        FullName 數(shù)據(jù)類型的完全限定名(包括命名空間名)
        Namespace 定義數(shù)據(jù)類型的命名空間名
        IsAbstract 指示該類型是否是抽象類型
        IsArray   指示該類型是否是數(shù)組
        IsClass   指示該類型是否是類
        IsEnum   指示該類型是否是枚舉
        IsInterface    指示該類型是否是接口
        IsPublic 指示該類型是否是公有的
        IsSealed 指示該類型是否是密封類
        IsValueType 指示該類型是否是值類型
    Type類的方法:
        GetConstructor(), GetConstructors():返回ConstructorInfo類型愤诱,用于取得該類的構(gòu)造函數(shù)的信息
        GetEvent(), GetEvents():返回EventInfo類型云头,用于取得該類的事件的信息
        GetField(), GetFields():返回FieldInfo類型,用于取得該類的字段(成員變量)的信息
        GetInterface(), GetInterfaces():返回InterfaceInfo類型转锈,用于取得該類實(shí)現(xiàn)的接口的信息
        GetMember(), GetMembers():返回MemberInfo類型盘寡,用于取得該類的所有成員的信息
        GetMethod(), GetMethods():返回MethodInfo類型,用于取得該類的方法的信息
        GetProperty(), GetProperties():返回PropertyInfo類型撮慨,用于取得該類的屬性的信息
    可以調(diào)用這些成員竿痰,其方式是調(diào)用Type的InvokeMember()方法脆粥,或者調(diào)用MethodInfo, PropertyInfo和其他類的Invoke()方法。 
    //查看類中的構(gòu)造方法:
        NewClassw nc = new NewClassw();
        Type t = nc.GetType();
        ConstructorInfo[] ci = t.GetConstructors();    //獲取類的所有構(gòu)造函數(shù)
        foreach (ConstructorInfo c in ci) //遍歷每一個(gè)構(gòu)造函數(shù)
        {
            ParameterInfo[] ps = c.GetParameters();    //取出每個(gè)構(gòu)造函數(shù)的所有參數(shù)
            foreach (ParameterInfo pi in ps)   //遍歷并打印所該構(gòu)造函數(shù)的所有參數(shù)
            {
                Console.Write(pi.ParameterType.ToString()+" "+pi.Name+",");
            }
            Console.WriteLine();
        }

用構(gòu)造函數(shù)動態(tài)生成對象:
        Type t = typeof(NewClassw);
        Type[] pt = new Type[2];
        pt[0] = typeof(string);
        pt[1] = typeof(string);
        //根據(jù)參數(shù)類型獲取構(gòu)造函數(shù) 
        ConstructorInfo ci = t.GetConstructor(pt); 
        //構(gòu)造Object數(shù)組影涉,作為構(gòu)造函數(shù)的輸入?yún)?shù) 
        object[] obj = new object[2]{"grayworm","hi.baidu.com/grayworm"};   
        //調(diào)用構(gòu)造函數(shù)生成對象 
        object o = ci.Invoke(obj);    
        //調(diào)用生成的對象的方法測試是否對象生成成功 
        //((NewClassw)o).show();  

    用Activator生成對象:
        Type t = typeof(NewClassw);
        //構(gòu)造函數(shù)的參數(shù) 
        object[] obj = new object[2] { "grayworm", "hi.baidu.com/grayworm" };   
        //用Activator的CreateInstance靜態(tài)方法变隔,生成新對象 
        object o = Activator.CreateInstance(t,"grayworm","hi.baidu.com/grayworm"); 
        //((NewClassw)o).show();

//查看類中的屬性:
        NewClassw nc = new NewClassw();
        Type t = nc.GetType();
        PropertyInfo[] pis = t.GetProperties();
        foreach(PropertyInfo pi in pis)
        {
            Console.WriteLine(pi.Name);
        }
//查看類中的public方法:
        NewClassw nc = new NewClassw();
        Type t = nc.GetType();
        MethodInfo[] mis = t.GetMethods();
        foreach (MethodInfo mi in mis)
        {
            Console.WriteLine(mi.ReturnType+" "+mi.Name);
        }
//查看類中的public字段
        NewClassw nc = new NewClassw();
        Type t = nc.GetType();
        FieldInfo[] fis = t.GetFields();
        foreach (FieldInfo fi in fis)
        {
            Console.WriteLine(fi.Name);
        } 
//用反射生成對象,并調(diào)用屬性蟹倾、方法和字段進(jìn)行操作 
        NewClassw nc = new NewClassw();
        Type t = nc.GetType();
        object obj = Activator.CreateInstance(t);
        //取得ID字段 
        FieldInfo fi = t.GetField("ID");
        //給ID字段賦值 
        fi.SetValue(obj, "k001");
        //取得MyName屬性 
        PropertyInfo pi1 = t.GetProperty("MyName");
        //給MyName屬性賦值 
        pi1.SetValue(obj, "grayworm", null);
        PropertyInfo pi2 = t.GetProperty("MyInfo");
        pi2.SetValue(obj, "hi.baidu.com/grayworm", null);
        //取得show方法 
        MethodInfo mi = t.GetMethod("show");
        //調(diào)用show方法 
        mi.Invoke(obj, null);

System.Reflection.Assembly類

Assembly類可以獲得程序集的信息匣缘,也可以動態(tài)的加載程序集,以及在程序集中查找類型信息鲜棠,并創(chuàng)
建該類型的實(shí)例肌厨。
使用Assembly類可以降低程序集之間的耦合,有利于軟件結(jié)構(gòu)的合理化豁陆。
通過程序集名稱返回Assembly對象
Assembly ass = Assembly.Load("ClassLibrary831");
通過DLL文件名稱返回Assembly對象
Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");
通過Assembly獲取程序集中類
Type t = ass.GetType("ClassLibrary831.NewClass"); //參數(shù)必須是類的全名
通過Assembly獲取程序集中所有的類
Type[] t = ass.GetTypes();

//通過程序集的名稱反射
Assembly ass = Assembly.Load("ClassLibrary831");
    Type t = ass.GetType("ClassLibrary831.NewClass");
object o = Activator.CreateInstance(t, "grayworm", "http://hi.baidu.com/grayworm");
    MethodInfo mi = t.GetMethod("show");
    mi.Invoke(o, null);

//通過DLL文件全名反射其中的所有類型
    Assembly assembly = Assembly.LoadFrom("xxx.dll的路徑");
    Type[] aa = a.GetTypes();
    foreach(Type t in aa)
    {
        if(t.FullName == "a.b.c")
        {
            object o = Activator.CreateInstance(t);
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柑爸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子盒音,更是在濱河造成了極大的恐慌表鳍,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祥诽,死亡現(xiàn)場離奇詭異譬圣,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)雄坪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門厘熟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诸衔,你說我怎么就攤上這事盯漂。” “怎么了笨农?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵就缆,是天一觀的道長。 經(jīng)常有香客問我谒亦,道長竭宰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任份招,我火速辦了婚禮切揭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锁摔。我一直安慰自己廓旬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布谐腰。 她就那樣靜靜地躺著孕豹,像睡著了一般涩盾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上励背,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天春霍,我揣著相機(jī)與錄音,去河邊找鬼叶眉。 笑死址儒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的衅疙。 我是一名探鬼主播莲趣,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼炼蛤!你這毒婦竟也來了妖爷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤理朋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后绿聘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嗽上,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年熄攘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了兽愤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挪圾,死狀恐怖浅萧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哲思,我是刑警寧澤洼畅,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站棚赔,受9級特大地震影響帝簇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜靠益,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一丧肴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧胧后,春花似錦芋浮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镇草。三九已至,卻和暖如春何暇,著一層夾襖步出監(jiān)牢的瞬間陶夜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工裆站, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留条辟,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓宏胯,卻偏偏與公主長得像羽嫡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子肩袍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理杭棵,服務(wù)發(fā)現(xiàn),斷路器氛赐,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 轉(zhuǎn)自博客園 反射是.NET中的重要機(jī)制魂爪,通過反射,可以在運(yùn)行時(shí)獲得程序或程序集中每一個(gè)類型(包括類艰管、結(jié)構(gòu)滓侍、委托、接...
    極客詩人閱讀 936評論 0 0
  • hi牲芋,Anna 夏天過去了撩笆,你的那位情人大概也從囚禁的無名之地被放出來了吧?好在你還那么堅(jiān)強(qiáng)的等待缸浦,帶著...
    Anna的小cici閱讀 188評論 0 0
  • 相冊圖片預(yù)取緩存策略是內(nèi)存緩存(硬引用LruCache夕冲、軟引用SoftReference)、外部文件緩存(cont...
    博為峰51Code教研組閱讀 175評論 0 0