欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android ARouter路由框架解析

 更新時(shí)間:2018年04月02日 11:02:16   作者:OneXzgj  
這篇文章主要介紹了Android ARouter路由框架解析,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

一、ARouter介紹及主要應(yīng)用場(chǎng)景:

1、介紹:

是ARouter是阿里巴巴開源的Android平臺(tái)中對(duì)頁(yè)面、服務(wù)提供路由功能的中間件,提倡的是簡(jiǎn)單且夠用。

2、原生的路由方案存在的問題

首先談一談原生的路由方案存在的問題以及為什么需要路由框架。我們所使用的原生路由方案一般是通過顯式intent和隱式intent兩種方式實(shí)現(xiàn)的,而在顯式intent的情況下,因?yàn)闀?huì)存在直接的類依賴的問題,導(dǎo)致耦合非常嚴(yán)重;而在隱式intent情況下,則會(huì)出現(xiàn)規(guī)則集中式管理,導(dǎo)致協(xié)作變得非常困難。而且一般而言配置規(guī)則都是在Manifest中的,這就導(dǎo)致了擴(kuò)展性較差。除此之外,使用原生的路由方案會(huì)出現(xiàn)跳轉(zhuǎn)過程無法控制的問題,因?yàn)橐坏┦褂昧薙tartActivity()就無法插手其中任何環(huán)節(jié)了,只能交給系統(tǒng)管理,這就導(dǎo)致了在跳轉(zhuǎn)失敗的情況下無法降級(jí),而是會(huì)直接拋出運(yùn)營(yíng)級(jí)的異常。

這時(shí)候如果考慮使用自定義的路由組件就可以解決以上的一些問題,比如通過URL索引就可以解決類依賴的問題;通過分布式管理頁(yè)面配置可以解決隱式intent中集中式管理Path的問題;自己實(shí)現(xiàn)整個(gè)路由過程也可以擁有良好的擴(kuò)展性,還可以通過AOP的方式解決跳轉(zhuǎn)過程無法控制的問題,與此同時(shí)也能夠提供非常靈活的降級(jí)方式。

3、為什么要用路由組件

為什么要用路由組件

前面提到的主要是開發(fā)與協(xié)作中的問題,而使用一款路由框架時(shí)還會(huì)涉及到其他的兩個(gè)大方面:一方面是組件化,而另一方面就是Native和H5的問題。剛才所提到的主要是開發(fā)和協(xié)作中作為開發(fā)者所需要面對(duì)的問題,而一旦一款A(yù)PP達(dá)到一定體量的時(shí)候,業(yè)務(wù)就會(huì)膨脹得比較嚴(yán)重,而開發(fā)團(tuán)隊(duì)的規(guī)模也會(huì)越來越大,這時(shí)候一般都會(huì)提出組件化的概念。組件化就是將APP按照一定的功能和業(yè)務(wù)拆分成多個(gè)小組件,不同的組件由不同的開發(fā)小組來負(fù)責(zé),這樣就可以解決大型APP開發(fā)過程中的開發(fā)與協(xié)作的問題,將這些問題分散到小的APP中。目前而言組件化已經(jīng)有非常多比較成熟的方案了,而自定義路由框架也可以非常好地解決整個(gè)APP完成組件化之后模塊之間沒有耦合的問題,因?yàn)闆]有耦合時(shí)使用原生的路由方案肯定是不可以的。

另外一個(gè)問題就是Native與H5的問題,因?yàn)楝F(xiàn)在的APP很少是純Native的,也很少會(huì)有純H5的,一般情況下都是將兩者進(jìn)行結(jié)合。這時(shí)候就需要非常便捷并且統(tǒng)一的跳轉(zhuǎn)方案,因?yàn)樵贖5中是無法使用StartActivity()跳轉(zhuǎn)到Native頁(yè)面的,而從Native跳轉(zhuǎn)到H5頁(yè)面也只能通過配置瀏覽器的方式實(shí)現(xiàn)。

4、路由框架的特點(diǎn)

為了解決以上的問題就需要實(shí)現(xiàn)一個(gè)自定義的路由框架,而路由框架一般都具有以下的三種特點(diǎn):

  1. 分發(fā):把一個(gè)URL或者請(qǐng)求按照一定的規(guī)則分配給一個(gè)服務(wù)或者頁(yè)面來處理,這個(gè)流程就是分發(fā),分發(fā)是路由框架最基本的功能,當(dāng)然也可以理解成為簡(jiǎn)單的跳轉(zhuǎn)。
  2. 管理:將組件和頁(yè)面按照一定的規(guī)則管理起來,在分發(fā)的時(shí)候提供搜索、加載、修改等操作,這部分就是管理,也是路由框架的基礎(chǔ),上層功能都是建立在管理之上。
  3. 控制:就像路由器一樣,路由的過程中,會(huì)有限速、屏蔽等一些控制操作,路由框架也需要在路由的過程中,對(duì)路由操作做一些定制性的擴(kuò)展,比方剛才提到的AOP,后期的功能更新,也是圍繞這個(gè)部分來做的。

5、ARouter的7個(gè)優(yōu)勢(shì)

優(yōu)勢(shì)一:直接解析URL路由,解析參數(shù)并賦值到對(duì)應(yīng)目標(biāo)字段的頁(yè)面中。
優(yōu)勢(shì)二:支持多模塊項(xiàng)目,因?yàn)楝F(xiàn)在很少有APP是單模塊的項(xiàng)目,一般都是多模塊單工程的,由不同的團(tuán)隊(duì)負(fù)責(zé)不同的模塊開發(fā),這時(shí)候支持多模塊項(xiàng)目開發(fā)就顯得尤為重要。
優(yōu)勢(shì)三:支持InstantRun,目前很多路由框架并不支持InstantRun,而InstantRun是Google在AndroidStudio2.0阿爾法版本中提供的新功能,其類似于代碼的日更新,其只不過面向的是開發(fā)過程,這樣做可以在開發(fā)的過程中減少開發(fā)和編譯的次數(shù),可以簡(jiǎn)單地將代碼修改即時(shí)地同步到APK中,從而可以大規(guī)模降低開發(fā)復(fù)雜度。
優(yōu)勢(shì)四:允許自定義攔截器,ARouter是支持?jǐn)r截器的,而攔截器其實(shí)就是AOP的實(shí)現(xiàn),可以自定義多個(gè)攔截器解決一些面向行為編程上出現(xiàn)的問題。
優(yōu)勢(shì)五:ARouter可以提供IoC容器,IoC其實(shí)就是控制反轉(zhuǎn),這一部分做過服務(wù)端開發(fā)的朋友可能比較了解,因?yàn)榉?wù)端開發(fā)經(jīng)常用到的Spring框架能夠提供的一個(gè)非常重要的能力就是控制反轉(zhuǎn)。
優(yōu)勢(shì)六:映射關(guān)系自動(dòng)注冊(cè),在頁(yè)面不是很多的小型APP上面,自動(dòng)注冊(cè)并不會(huì)體現(xiàn)出太大優(yōu)勢(shì),但是對(duì)于大型APP而言,可能頁(yè)面數(shù)量已經(jīng)達(dá)到的幾十個(gè)或者數(shù)百個(gè),在這樣的情況下,自動(dòng)注冊(cè)就顯得非常重要了,因?yàn)椴豢赡軐⒚恳粋€(gè)頁(yè)面都通過代碼的方式進(jìn)行注冊(cè)。
優(yōu)勢(shì)七:靈活的降級(jí)策略,ARouter可以提供很多種降級(jí)策略供用戶自行選擇,而原生的路由方案存在無法靈活降級(jí)的問題,StartActivity()一旦失敗將會(huì)拋出運(yùn)營(yíng)級(jí)異常。

6、應(yīng)用場(chǎng)景:

  1. 從外部URL映射到內(nèi)部頁(yè)面,以及參數(shù)傳遞與解析
  2. 跨模塊頁(yè)面跳轉(zhuǎn),模塊間解耦
  3. 攔截跳轉(zhuǎn)過程,處理登陸、埋點(diǎn)等邏輯
  4. 跨模塊API調(diào)用,通過控制反轉(zhuǎn)來做組件解耦

GitHub:https://github.com/alibaba/ARouter

二、ARouter的基本使用步驟:

1、添加依賴和配置

android {
  defaultConfig {
  ...
  javaCompileOptions {
    annotationProcessorOptions {
    arguments = [ moduleName : project.getName() ]
    }
  }
  }
}

dependencies {
  // 替換成最新版本, 需要注意的是api
  // 要與compiler匹配使用,均使用最新版可以保證兼容
  compile 'com.alibaba:arouter-api:x.x.x'
  annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
  ...
}
// 替換成最新版本, 需要注意的是api
// 要與compiler匹配使用,均使用最新版可以保證兼容
compile 'com.alibaba:arouter-api:x.x.x'
annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'

這里替換相應(yīng)的Api和compiler

2、添加注解及初始化

ARouter初始化

if (isDebug()) {      // 這兩行必須寫在init之前,否則這些配置在init過程中將無效
  ARouter.openLog();   // 打印日志
  ARouter.openDebug();  // 開啟調(diào)試模式(如果在InstantRun模式下運(yùn)行,必須開啟調(diào)試模式!線上版本需要關(guān)閉,否則有安全風(fēng)險(xiǎn))
}
ARouter.init(mApplication); // 盡可能早,推薦在Application中初始化

在需要跳轉(zhuǎn)的Activity上進(jìn)行注解配置

// 在支持路由的頁(yè)面上添加注解(必選)
// 這里的路徑需要注意的是至少需要有兩級(jí),/xx/xx
@Route(path = "/com/ARouter2Activity")
public class ARouter2Activity extends AppCompatActivity {
   super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_arouter2);
  //....
}

應(yīng)用中的簡(jiǎn)單跳轉(zhuǎn)

 ARouter.getInstance().build("/com/ARouter2Activity").navigation();

應(yīng)用中攜帶參數(shù)的跳轉(zhuǎn)

ARouter.getInstance().build("/com/ARouter2Activity")
            .withString("name","onex")
            .withInt("age",22)
            .navigation();

在目標(biāo)Activity中接受相關(guān)的參數(shù)

為每一個(gè)參數(shù)聲明一個(gè)字段,并使用 @Autowired 標(biāo)注

URL中不能傳遞Parcelable類型數(shù)據(jù),通過ARouter api可以傳遞

Parcelable對(duì)象

@Route(path = "/com/ARouter2Activity")
public class ARouter2Activityextends Activity {
  @Autowired
  public String name;
  @Autowired
  int age;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  ARouter.getInstance().inject(this);
  // ARouter會(huì)自動(dòng)對(duì)字段進(jìn)行賦值,無需主動(dòng)獲取
  Log.d("param", name + age + boy);
  }
}

這里需要注意的是

ARouter.getInstance().inject(this); 

三、進(jìn)階使用

1、Activity之間傳遞自定義對(duì)象

如果需要傳遞自定義對(duì)象,需要實(shí)現(xiàn) SerializationService,并使用@Route注解標(biāo)注(方便用戶自行選擇序列化方式)

@Route(path = "/service/json")
public class JsonServiceImpl implements SerializationService {
  @Override
  public void init(Context context) {

  }

  @Override
  public <T> T json2Object(String text, Class<T> clazz) {
    return JSON.parseObject(text, clazz);
  }

  @Override
  public String object2Json(Object instance) {
    return JSON.toJSONString(instance);
  }
}

以下是ARouter支持的傳遞的數(shù)據(jù)類型 

TestParcelable testParcelable = new TestParcelable("jack", 666);
        TestObj testObj = new TestObj("Rose", 777);
        List<TestObj> objList = new ArrayList<>();
        objList.add(testObj);

        Map<String, List<TestObj>> map = new HashMap<>();
        map.put("testMap", objList);

        ARouter.getInstance().build("/test/activity1")
            .withString("name", "老王")
            .withInt("age", 18)
            .withBoolean("boy", true)
            .withLong("high", 180)
            .withString("url", "https://a.b.c")
            .withParcelable("pac", testParcelable)
            .withObject("obj", testObj)
            .withObject("objList", objList)
            .withObject("map", map)
            .navigation();

需要注意的是:我們?cè)趥鬟f的時(shí)候使用的是什么樣的KEY,在目標(biāo)Activity的地方使用相同的KEY,進(jìn)行聲明變量例如:

Man man = new Man("OneX","男");
ARouter.getInstance().build("/com/ARouter2Activity")
    .withObject("obj",man)
    .navigation();

目標(biāo)頁(yè)面Code

 @Autowired
  Man obj;

2、通過Url進(jìn)行跳轉(zhuǎn)

新建一個(gè)Activity用于監(jiān)聽Schame事件,之后直接把url傳遞給ARouter即可(類似于轉(zhuǎn)發(fā)路由的Activity)

public class SchameFilterActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  Uri uri = getIntent().getData();
  ARouter.getInstance().build(uri).navigation();
  finish();
  }
}

在AndroidManifest.xml中進(jìn)行如下配置

<activity android:name=".activity.SchameFilterActivity">
  <!-- Schame -->
  <intent-filter>
    <data
    android:host="m.aliyun.com"
    android:scheme="arouter"/>

    <action android:name="android.intent.action.VIEW"/>

    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
  </intent-filter>
</activity>

3、設(shè)置攔截器

比較經(jīng)典的應(yīng)用就是在跳轉(zhuǎn)過程中處理登陸事件,這樣就不需要在目標(biāo)頁(yè)重復(fù)做登陸檢攔截器會(huì)在跳轉(zhuǎn)之間執(zhí)行

多個(gè)攔截器會(huì)按優(yōu)先級(jí)順序依次執(zhí)行

@Interceptor(priority = 8, name = "測(cè)試用攔截器")
public class TestInterceptor implements IInterceptor {
  @Override
  public void process(Postcard postcard, InterceptorCallback callback) {
  ...
  callback.onContinue(postcard); // 處理完成,交還控制權(quán)
  // callback.onInterrupt(new RuntimeException("我覺得有點(diǎn)異常"));   // 覺得有問題,中斷路由流程

  // 以上兩種至少需要調(diào)用其中一種,否則不會(huì)繼續(xù)路由
  }

  @Override
  public void init(Context context) {
  // 攔截器的初始化,會(huì)在sdk初始化的時(shí)候調(diào)用該方法,僅會(huì)調(diào)用一次
  }
}

4、監(jiān)聽路由跳轉(zhuǎn)結(jié)果

// 使用兩個(gè)參數(shù)的navigation方法,可以獲取單次跳轉(zhuǎn)的結(jié)果
ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
  @Override
  public void onFound(Postcard postcard) {
   ...
  }

  @Override
  public void onLost(Postcard postcard) {
  ...
  }
});

5、獲取Fragment的對(duì)象

// 獲取Fragment
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();

6、通過依賴注入解耦:服務(wù)管理,暴露服務(wù)

// 聲明接口,其他組件通過接口來調(diào)用服務(wù)
public interface HelloService extends IProvider {
  String sayHello(String name);
}

// 實(shí)現(xiàn)接口
@Route(path = "/service/hello", name = "測(cè)試服務(wù)")
public class HelloServiceImpl implements HelloService {

  @Override
  public String sayHello(String name) {
  return "hello, " + name;
  }

  @Override
  public void init(Context context) {

  }
}

在Class中的相關(guān)使用

public class Test {
  @Autowired
  HelloService helloService;

  @Autowired(name = "/service/hello")
  HelloService helloService2;

  HelloService helloService3;

  HelloService helloService4;

  public Test() {
  ARouter.getInstance().inject(this);
  }

  public void testService() {
   // 1. (推薦)使用依賴注入的方式發(fā)現(xiàn)服務(wù),通過注解標(biāo)注字段,即可使用,無需主動(dòng)獲取
   // Autowired注解中標(biāo)注name之后,將會(huì)使用byName的方式注入對(duì)應(yīng)的字段,不設(shè)置name屬性,會(huì)默認(rèn)使用byType的方式發(fā)現(xiàn)服務(wù)(當(dāng)同一接口有多個(gè)實(shí)現(xiàn)的時(shí)候,必須使用byName的方式發(fā)現(xiàn)服務(wù))
  helloService.sayHello("Vergil");
  helloService2.sayHello("Vergil");

  // 2. 使用依賴查找的方式發(fā)現(xiàn)服務(wù),主動(dòng)去發(fā)現(xiàn)服務(wù)并使用,下面兩種方式分別是byName和byType
  helloService3 = ARouter.getInstance().navigation(HelloService.class);
  helloService4 = (HelloService) ARouter.getInstance().build("/service/hello").navigation();
  helloService3.sayHello("Vergil");
  helloService4.sayHello("Vergil");
  }
}

四、注意事項(xiàng)及混淆配置

1、初始化中的其他配置

ARouter.openLog(); // 開啟日志
ARouter.openDebug(); // 使用InstantRun的時(shí)候,需要打開該開關(guān),上線之后關(guān)閉,否則有安全風(fēng)險(xiǎn)
ARouter.printStackTrace(); // 打印日志的時(shí)候打印線程堆棧

2、詳細(xì)API:

// 構(gòu)建標(biāo)準(zhǔn)的路由請(qǐng)求
ARouter.getInstance().build("/home/main").navigation();

// 構(gòu)建標(biāo)準(zhǔn)的路由請(qǐng)求,并指定分組
ARouter.getInstance().build("/home/main", "ap").navigation();

// 構(gòu)建標(biāo)準(zhǔn)的路由請(qǐng)求,通過Uri直接解析
Uri uri;
ARouter.getInstance().build(uri).navigation();

// 構(gòu)建標(biāo)準(zhǔn)的路由請(qǐng)求,startActivityForResult
// navigation的第一個(gè)參數(shù)必須是Activity,第二個(gè)參數(shù)則是RequestCode
ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);

// 直接傳遞Bundle
Bundle params = new Bundle();
ARouter.getInstance()
  .build("/home/main")
  .with(params)
  .navigation();

// 指定Flag
ARouter.getInstance()
  .build("/home/main")
  .withFlags();
  .navigation();

// 獲取Fragment
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
          
// 對(duì)象傳遞
ARouter.getInstance()
  .withObject("key", new TestObj("Jack", "Rose"))
  .navigation();

// 覺得接口不夠多,可以直接拿出Bundle賦值
ARouter.getInstance()
    .build("/home/main")
    .getExtra();

// 轉(zhuǎn)場(chǎng)動(dòng)畫(常規(guī)方式)
ARouter.getInstance()
  .build("/test/activity2")
  .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
  .navigation(this);

// 轉(zhuǎn)場(chǎng)動(dòng)畫(API16+)
ActivityOptionsCompat compat = ActivityOptionsCompat.
  makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);

// ps. makeSceneTransitionAnimation 使用共享元素的時(shí)候,需要在navigation方法中傳入當(dāng)前Activity

ARouter.getInstance()
  .build("/test/activity2")
  .withOptionsCompat(compat)
  .navigation();
    
// 使用綠色通道(跳過所有的攔截器)
ARouter.getInstance().build("/home/main").greenChannel().navigation();

// 使用自己的日志工具打印日志
ARouter.setLogger();

3、路由中的分組概念

SDK中針對(duì)所有的路徑(/test/1 /test/2)進(jìn)行分組,分組只有在分組中的某一個(gè)路徑第一次被訪問的時(shí)候,該分組才會(huì)被初始化

通過 @Route 注解主動(dòng)指定分組,否則使用路徑中第一段字符串(/*/)作為分組

注意:一旦主動(dòng)指定分組之后,應(yīng)用內(nèi)路由需要使用 ARouter.getInstance().build(path, group) 進(jìn)行跳轉(zhuǎn),手動(dòng)指定分組,否則無法找到

@Route(path = "/test/1", group = "app")

4、添加混淆規(guī)則(如果使用了Proguard)

-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

# 如果使用了 byType 的方式獲取 Service,需添加下面規(guī)則,保護(hù)接口
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider

# 如果使用了 單類注入,即不定義接口實(shí)現(xiàn) IProvider,需添加下面規(guī)則,保護(hù)實(shí)現(xiàn)
-keep class * implements com.alibaba.android.arouter.facade.template.IProvider

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android自定義View繪制貝塞爾曲線中小紅點(diǎn)的方法

    Android自定義View繪制貝塞爾曲線中小紅點(diǎn)的方法

    貝塞爾曲線的本質(zhì)是通過數(shù)學(xué)計(jì)算的公式來繪制平滑的曲線,分為一階,二階,三階及多階。但是這里不講數(shù)學(xué)公式和驗(yàn)證,那些偉大的數(shù)學(xué)家已經(jīng)證明過了,所以就只講講Android開發(fā)中的運(yùn)用吧
    2023-02-02
  • Android Activity之間的數(shù)據(jù)傳遞方法總結(jié)

    Android Activity之間的數(shù)據(jù)傳遞方法總結(jié)

    這篇文章主要給大家總結(jié)介紹了關(guān)于Android Activity之間的數(shù)據(jù)傳遞方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Android實(shí)現(xiàn)注冊(cè)登錄界面的實(shí)例代碼

    Android實(shí)現(xiàn)注冊(cè)登錄界面的實(shí)例代碼

    這篇文章主要介紹了Android實(shí)現(xiàn)注冊(cè)登錄界面的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • 分享Android開發(fā)自學(xué)筆記之AndroidStudio常用功能

    分享Android開發(fā)自學(xué)筆記之AndroidStudio常用功能

    這篇文章主要給大家分享Android開發(fā)自學(xué)筆記之AndroidStudio常用功能的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • Java4Android開發(fā)教程(三)java基本概念

    Java4Android開發(fā)教程(三)java基本概念

    本文介紹了Java4Android的基本概念,都是開發(fā)必備的基礎(chǔ)知識(shí),希望能對(duì)大家有所幫助
    2014-10-10
  • Android自定義view倒計(jì)時(shí)60秒

    Android自定義view倒計(jì)時(shí)60秒

    這篇文章主要為大家詳細(xì)介紹了Android自定義view倒計(jì)時(shí)60秒,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Flutter軟鍵盤的原理淺析

    Flutter軟鍵盤的原理淺析

    大家應(yīng)該都知道目前Flutter官方是沒有自定義鍵盤的解決方案,下面這篇文章主要給大家介紹了關(guān)于Flutter軟鍵盤原理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-10-10
  • Android編程中光線傳感器的調(diào)用方法詳解

    Android編程中光線傳感器的調(diào)用方法詳解

    這篇文章主要介紹了Android編程中光線傳感器的調(diào)用方法,結(jié)合實(shí)例形式分析了Android光線傳感器的調(diào)用方法、函數(shù)、屬性相關(guān)使用技巧,需要的朋友可以參考下
    2017-08-08
  • Android實(shí)現(xiàn)MVVM架構(gòu)數(shù)據(jù)刷新詳解流程

    Android實(shí)現(xiàn)MVVM架構(gòu)數(shù)據(jù)刷新詳解流程

    MVVM架構(gòu)模式,即Model-View-ViewModel三個(gè)層級(jí),MVVM模式出來的時(shí)間已經(jīng)很長(zhǎng)了,網(wǎng)上關(guān)于MVVM模式的解析也有很多,我這里只說一下我自己的理解,基本上是和MVP模式相比較的一個(gè)差異
    2021-10-10
  • Android把svg圖片轉(zhuǎn)為jpg保存到相冊(cè)圖庫(kù)

    Android把svg圖片轉(zhuǎn)為jpg保存到相冊(cè)圖庫(kù)

    這篇文章主要為大家詳細(xì)介紹了Android把svg圖片轉(zhuǎn)為jpg保存到相冊(cè)圖庫(kù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05

最新評(píng)論