React Native Android混合開發(fā)

期待已久的新課上線啦!解鎖React Native開發(fā)新姿勢(shì),一網(wǎng)打盡React Native最新與最熱技術(shù),點(diǎn)我Get!!!

在React Native的應(yīng)用場(chǎng)景中,有時(shí)候一個(gè)APP只有部分頁(yè)面是由React Native實(shí)現(xiàn)的,比如:我們常用的攜程App,它的首頁(yè)下的很多模塊都是由React Native實(shí)現(xiàn)的,這種開發(fā)模式被稱為混合開發(fā)。

混合開發(fā)的一些其他應(yīng)用場(chǎng)景:

在原有項(xiàng)目中加入RN頁(yè)面,在RN項(xiàng)目中加入原生頁(yè)面

RNHybrid

原生頁(yè)面中嵌入RN模塊

Native-RN-page

RN頁(yè)面中嵌入原生模塊

RN-Native-page

以上這些都屬于React Native混合開發(fā)的范疇,那么如何進(jìn)行React Native混合開發(fā)呢?

在這篇文章中我將向大家介紹React Native混合開發(fā)的流程,需要掌握的技術(shù),以及一些經(jīng)驗(yàn)技巧,與該文章配套的還有React Native與Android 混合開發(fā)講解的視頻教程。

React Native混合開發(fā)的教程我們分為上下兩篇,上篇主要介紹如何在現(xiàn)有的Android應(yīng)用上進(jìn)行React Native混合開發(fā),下篇主要介紹如何在現(xiàn)有的iOS應(yīng)用上進(jìn)行React Native混合開發(fā)。

將React Native集成到現(xiàn)有的Android應(yīng)用中需要如下幾個(gè)主要步驟:

  • 首先,你需要有一個(gè)React Native項(xiàng)目;
  • 為已存在的Android應(yīng)用添加React Native所需要的依賴;
  • 創(chuàng)建index.js并添加你的React Native代碼;
  • 創(chuàng)建一個(gè)Activity來(lái)承載React Native,在這個(gè)Activity中創(chuàng)建一個(gè)ReactRootView來(lái)作為React Native服務(wù)的容器;
  • 啟動(dòng)React Native的Packager服務(wù),運(yùn)行應(yīng)用;
  • (可選)根據(jù)需要添加更多React Native的組件;
  • 運(yùn)行、調(diào)試、打包、發(fā)布應(yīng)用;
  • 升職加薪、迎娶白富美,走向人生巔峰!;

1. 創(chuàng)建一個(gè)React Native項(xiàng)目

在做混合開發(fā)之前我們首先需要?jiǎng)?chuàng)建一個(gè)沒(méi)有Android和iOS模塊的React Native項(xiàng)目。我們可以通過(guò)兩種方式來(lái)創(chuàng)建一個(gè)這樣的React Native項(xiàng)目:

  • 通過(guò)npm安裝react-native的方式添加一個(gè)React Native項(xiàng)目;
  • 通過(guò)react-native init來(lái)初始化一個(gè)React Native項(xiàng)目;

通過(guò)npm安裝react-native的方式添加一個(gè)React Native項(xiàng)目

第一步:創(chuàng)建一個(gè)名為RNHybridApp的目錄,然后在該目錄下添加一個(gè)包含如下信息的package.json

{
  "name": "RNHybrid",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  }
}

第二步:在為package.json添加react-native

在該目錄下執(zhí)行:

npm install --save react-native

執(zhí)行完上述命令之后,你會(huì)看到如下警告:

npm-install--save-react-native.png

其中,有一條警告npm WARN react-native@0.55.4 requires a peer of react@16.3.1 but none is installed告訴我們需要安裝react@16.3.1

npm install --save react@16.3.1

至此,一個(gè)不含Android和iOS模塊的React Native項(xiàng)目便創(chuàng)建好了。此過(guò)程所遇到的更多問(wèn)題可查閱:React Native與Android 混合開發(fā)講解的視頻教程

提示:npm 會(huì)在你的目錄下創(chuàng)建一個(gè)node_modulesnode_modules體積很大且是動(dòng)態(tài)生成了,建議將其添加到.gitignore文件中;

通過(guò)react-native init來(lái)初始化一個(gè)React Native項(xiàng)目

除了上述方式之外,我們也可以通過(guò)react-native init命令來(lái)初始化一個(gè)React Native項(xiàng)目。

react-native init RNHybrid

上述命令會(huì)初始化一個(gè)完成的名為RNHybrid的React Native項(xiàng)目,然后我們將里面的androidios目錄刪除,替換成已存在Android和iOS項(xiàng)目。

2. 添加React Native所需要的依賴

在上文中我們已經(jīng)創(chuàng)建了個(gè)一個(gè)React Native項(xiàng)目,接下來(lái)我們來(lái)看一下如何將這個(gè)React Native項(xiàng)目和我們已經(jīng)存在的Native項(xiàng)目進(jìn)行融合。

在進(jìn)行融合之前我們需要將已經(jīng)存在的Native項(xiàng)目放到我們創(chuàng)建的RNHybrid下,比如:我有一個(gè)名為RNHybridAndroid的Android項(xiàng)目,將其放到RNHybrid目錄下:

RNHybrid
├── RNHybridAndroid
├── package.json
├── node_modules
└── .gitignore

第一步:配置maven

接下來(lái)我們需要為已經(jīng)存在的RNHybridAndroid項(xiàng)目添加 React Native依賴,在RNHybrid/RNHybridAndroid/app/build.gradle文件中添加如下代碼:

dependencies {
    compile 'com.android.support:appcompat-v7:23.0.1'
    ...
    compile "com.facebook.react:react-native:+" // From node_modules
}
app-build.gradle

然后,我們?yōu)镽NHybridAndroid項(xiàng)目配置使用的本地React Native maven目錄,在RNHybrid/RNHybridAndroid/build.gradle文件中添加如下代碼:

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        ...
    }
    ...
}
maven-directory-to-build.gradle

提示:為確保你配置的目錄正確,可以通過(guò)在Android Studio中運(yùn)行Gradle sync 看是否有 “Failed to resolve: com.facebook.react:react-native:0.x.x" 的錯(cuò)誤出現(xiàn),沒(méi)有錯(cuò)誤則說(shuō)明配置正確,否則說(shuō)明配置路由有問(wèn)題。
此過(guò)程所遇到的更多問(wèn)題可查閱:React Native與Android 混合開發(fā)講解的視頻教程

第二步:配置權(quán)限

接下來(lái)我們?yōu)锳PP運(yùn)行配置所需要的權(quán)限:檢查你項(xiàng)目中的AndroidManifest.xml文件中看是否有如下權(quán)限:

<uses-permission android:name="android.permission.INTERNET" />

如果沒(méi)有,則需要將上述權(quán)限添加到AndroidManifest.xml中。

另外,如果你需要用到RN的Dev Settings功能:

DevSettingsActivity

則需要在AndroidManifest.xml文件中添加如下代碼:

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

提示:上述圖片就是RN 開發(fā)調(diào)試彈框中的Dev Settings功能,打開該功能會(huì)彈出上圖的一個(gè)界面,這個(gè)界面就是DevSettingsActivity。

第三步:指定要ndk需要兼容的架構(gòu)(重要)

Android不能同時(shí)加載多種架構(gòu)的so庫(kù),現(xiàn)在很多Android第三方sdks對(duì)abi的支持比較全,可能會(huì)包含armeabi, armeabi-v7a,x86, arm64-v8a,x86_64五種abi,如果不加限制直接引用會(huì)自動(dòng)編譯出支持5種abi的APK,而Android設(shè)備會(huì)從這些abi進(jìn)行中優(yōu)先選擇某一個(gè),比如:arm64-v8a,但如果其他sdk不支持這個(gè)架構(gòu)的abi的話就會(huì)出現(xiàn)crash。如下圖:

libgnustl_shared.so"-is-32-bit-instead-of-64-bit

怎么解決呢:

app/gradle 文件中添加如下代碼:

defaultConfig {
....?
    ndk {
        abiFilters "armeabi-v7a", "x86"
    }
}

上述代碼的意思是,限制打包的so庫(kù)只包含armeabi-v7ax86此過(guò)程所遇到的更多問(wèn)題可查閱:React Native與Android 混合開發(fā)講解的視頻教程

可參考:libgnustl_shared.so" is 32-bit instead of 64-bit

3.創(chuàng)建index.js并添加你的React Native代碼

通過(guò)上述兩步,我們已經(jīng)為RNHybridAndroid項(xiàng)目添加了React Native依賴,接下來(lái)我們來(lái)開發(fā)一些JS代碼。

在RNHybrid目錄下創(chuàng)建一個(gè)index.js文件并添加如下代碼:

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('App1', () => App);

上述代碼,AppRegistry.registerComponent('App1', () => App);目的是向React Native注冊(cè)一個(gè)名為App1的組件,然后我會(huì)在第四步給大家介紹如何在Android中加載并顯示出這個(gè)組件。

另外,在上述代碼中我們引用了一個(gè)App.js文件:

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';

type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          this is App
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  }
 });

這個(gè)App.js文件代表了我們React Native的一個(gè)頁(yè)面,在這個(gè)頁(yè)面中顯示了this is App的文本內(nèi)容。

以上就是為本次演示所添加的React Native代碼,你也可以根據(jù)需要添加更多的React Native代碼以及組件出來(lái)。

4. 為React Native創(chuàng)建一個(gè)Activity來(lái)作為容器

經(jīng)過(guò)上述3、4步,我們已經(jīng)為RNHybridAndroid項(xiàng)目添加了React Native依賴,并且創(chuàng)建一些React Native代碼和注冊(cè)了一個(gè)名為App1的組件,接下來(lái)我們來(lái)學(xué)習(xí)下如何在RNHybridAndroid項(xiàng)目中使用這個(gè)App1組件。

創(chuàng)建RNPageActivity

首先我們需要?jiǎng)?chuàng)建一個(gè)Activity來(lái)作為React Native的容器,

public class RNPageActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
            .setApplication(getApplication())
            .setBundleAssetName("index.android.bundle")
            .setJSMainModulePath("index")
            .addPackage(new MainReactPackage())
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .build();
        // 這個(gè)"App1"名字一定要和我們?cè)趇ndex.js中注冊(cè)的名字保持一致AppRegistry.registerComponent()
        mReactRootView.startReactApplication(mReactInstanceManager, "App1", null);

        setContentView(mReactRootView);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }
}

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

  • setBundleAssetName:打包時(shí)放在assets目錄下的JS bundle包的名字,App release之后會(huì)從該目錄下加載JS bundle;
  • setJSMainModulePath:JS bundle中主入口的文件名,也就是我們上文中創(chuàng)建的那個(gè)index.js文件;
  • addPackage:向RN添加Native Moudle,在上述代碼中我們添加了new MainReactPackage()這個(gè)是必須的,另外,如果我們創(chuàng)建一些其他的Native Moudle也需要通過(guò)addPackage的方式將其注冊(cè)到RN中。需要指出的是RN除了這個(gè)方法外,也提供了一個(gè)addPackages方法用于批量向RN添加Native Moudle;
  • setUseDeveloperSupport:設(shè)置RN是否開啟開發(fā)者模式(debugging,reload,dev memu),比如我們常用開發(fā)者彈框;
  • setInitialLifecycleState:通過(guò)這個(gè)方法來(lái)設(shè)置RN初始化時(shí)所處的生命周期狀態(tài),一般設(shè)置成LifecycleState.RESUMED就行,和下文講的Activity容器的生命周期狀態(tài)關(guān)聯(lián);
  • mReactRootView.startReactApplication:它的第一個(gè)參數(shù)是mReactInstanceManager,第二個(gè)參數(shù)是我們?cè)?code>index.js中注冊(cè)的組件的名字,第三個(gè)參數(shù)接受一個(gè)Bundle來(lái)作為RN初始化時(shí)傳遞給JS的初始化數(shù)據(jù),它的具體用法我會(huì)在React Android 混合開發(fā)講解的視頻教程中再具體的講解;

在中AndroidManifest.xml注冊(cè)一個(gè)RNPageActivity

Android系統(tǒng)要求,每一個(gè)要打開的Activity都要在AndroidManifest.xml中進(jìn)行注冊(cè):

<activity
    android:name=".RNPageActivity"
    android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
    android:windowSoftInputMode="adjustResize"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar" />

上述代碼中我們?yōu)?code>RNPageActivity添加了一個(gè)@style/Theme.AppCompat.Light.NoActionBar類型的theme,這也是React Native UI組件所要求的主題。

為ReactInstanceManager添加Activity的生命周期回調(diào)

一個(gè) ReactInstanceManager可以被多個(gè)activities或fragments共享,所以我們需要在Activity的生命周期中回調(diào)ReactInstanceManager的對(duì)于的方法。

 @Override
protected void onPause() {
    super.onPause();

    if (mReactInstanceManager != null) {
        mReactInstanceManager.onHostPause(this);
    }
}

@Override
protected void onResume() {
    super.onResume();

    if (mReactInstanceManager != null) {
        mReactInstanceManager.onHostResume(this, this);
    }
}

@Override
public void onBackPressed() {
    if (mReactInstanceManager != null) {
        mReactInstanceManager.onBackPressed();
    } else {
        super.onBackPressed();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();

    if (mReactInstanceManager != null) {
        mReactInstanceManager.onHostDestroy(this);
    }
    if (mReactRootView != null) {
        mReactRootView.unmountReactApplication();
    }
}

從上述代碼中你會(huì)發(fā)現(xiàn)有個(gè)不屬于Activity生命周期中的方法onBackPressed,添加它的目的主要是為了當(dāng)用戶單擊手機(jī)的返回鍵之后將事件傳遞給JS,如果JS消費(fèi)了這個(gè)事件,Native就不再消費(fèi)了,如果JS沒(méi)有消費(fèi)這個(gè)事件那么RN會(huì)回調(diào)invokeDefaultOnBackPressed代碼。

@Override
public void invokeDefaultOnBackPressed() {
    super.onBackPressed();
}

此過(guò)程更細(xì)致的講解可查閱:React Native與Android 混合開發(fā)講解的視頻教程

添加開發(fā)者菜單

在RN中有個(gè)很好用的工具開發(fā)者菜單,我們平時(shí)調(diào)試RN應(yīng)用時(shí)對(duì)它的使用頻率很高,接下來(lái)我們來(lái)為RNHybridAndroid添加開著菜單。

 public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (getUseDeveloperSupport()) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {//Ctrl + M 打開RN開發(fā)者菜單
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
    }
    return super.onKeyUp(keyCode, event);
}

通過(guò)上代碼即可監(jiān)聽(tīng)Ctrl + M來(lái)打開RN開發(fā)者菜單。

ctrl+m-android

另外,RN也提供了雙擊R來(lái)快速加載JS的功能,通過(guò)如下代碼即可打開該功能:

public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (getUseDeveloperSupport()) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {//Ctrl + M 打開RN開發(fā)者菜單
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer).didDoubleTapR(keyCode, getCurrentFocus());
        if (didDoubleTapR) {//雙擊R 重新加載JS
            mReactInstanceManager.getDevSupportManager().handleReloadJS();
            return true;
        }
    }
    return super.onKeyUp(keyCode, event);
}

此過(guò)程更細(xì)致的講解可查閱:React Native與Android 混合開發(fā)講解的視頻教程

使用ReactActivity來(lái)作為RN容器

在上述的代碼中我們都是通過(guò)ReactInstanceManager來(lái)創(chuàng)建和加載JS的,然后重寫了Activity的生命周期來(lái)對(duì)ReactInstanceManager進(jìn)行回調(diào),另外,重寫了onKeyUp來(lái)啟用開發(fā)者菜單等功能。

另外,查看RN的源碼你會(huì)發(fā)現(xiàn)在RN sdk中有個(gè)叫ReactActivity的Activity,該Activity是RN官方封裝的一個(gè)RN容器。另外,在通過(guò)react-native init命令初始化的一個(gè)項(xiàng)目中你會(huì)發(fā)現(xiàn)有個(gè)MainActivity是繼承ReactActivity的,接下來(lái)我們就來(lái)繼承ReactActivity來(lái)封裝一個(gè)RN容器。

public class ReactPageActivity extends ReactActivity implements IJSBridge{
    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "App1";
    }
}

另外,我們需要實(shí)現(xiàn)一個(gè)MainApplication并添加如下代碼:

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage()
      );
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

上述代碼的主要作用是為ReactActivity提供ReactNativeHost,查看源碼你會(huì)發(fā)現(xiàn)在ReactActivity中使用了ReactActivityDelegate,在ReactActivityDelegate中會(huì)用到MainApplication中提供的ReactNativeHost

 protected ReactNativeHost getReactNativeHost() {
    return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
}

另外實(shí)現(xiàn)了MainApplication之后需要在AndroidManifest.xml中添加MainApplication

 <application
        android:name=".MainApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        ...

以上就是通過(guò)繼承ReactActivity的方式來(lái)作為RN容器的。

那么這兩種方式各有什么特點(diǎn):

  • 通過(guò)ReactInstanceManager的方式:靈活,可定制性強(qiáng);
  • 通過(guò)繼承ReactActivity的方式:簡(jiǎn)單,可定制性差;

此過(guò)程更細(xì)致的講解可查閱:React Native與Android 混合開發(fā)講解的視頻教程

5. 運(yùn)行React Native

經(jīng)過(guò)上述的步驟,我們已經(jīng)完成了對(duì)一個(gè)現(xiàn)有Android項(xiàng)目RNHybridAndroid添加了RN,并且通過(guò)兩種方式分別創(chuàng)建了一個(gè)RNPageActivityReactPageActivity的Activity來(lái)加載我們?cè)贘S中注冊(cè)的名為App1的RN 組件。

接下來(lái)我們來(lái)啟動(dòng)RN服務(wù)器,運(yùn)行RNHybridAndroid項(xiàng)目打開RNPageActivityReactPageActivity來(lái)查看效果:

npm start

RNHybrid的根目錄運(yùn)行上述命令,來(lái)啟動(dòng)一個(gè)RN本地服務(wù):

npm-start

然后我們打開AndroidStudio,點(diǎn)擊運(yùn)行按鈕或者通過(guò)快捷鍵Ctrl+R來(lái)將RNHybridAndroid安裝到模擬器上:

this-is-app-android

6. 添加更多React Native的組件

我們可以根據(jù)需要添加更多的React Native的組件:

import { AppRegistry } from 'react-native';
import App from './App';
import App2 from './App2';

AppRegistry.registerComponent('App1', () => App);
AppRegistry.registerComponent('App2', () => App);

然后,在Native中根據(jù)需要加載指定名字的RN組件即可。

7. 調(diào)試、打包、發(fā)布應(yīng)用

調(diào)試

調(diào)試這種混合的RN應(yīng)用和調(diào)試一個(gè)純RN應(yīng)用時(shí)一樣的,都是通過(guò)上文中說(shuō)講到的RN 開發(fā)者菜單,另外搭建也可以通過(guò)學(xué)習(xí)React Native技術(shù)精講與高質(zhì)量上線APP開發(fā)課程來(lái)掌握更多RN調(diào)試的技巧。

打包

雖讓,通過(guò)上述步驟,我們將RN和我們的RNHybridAndroid項(xiàng)目做了融合,但打包RNHybridAndroid你會(huì)發(fā)現(xiàn)里面并不包含JS部分的代碼,如果要將JS代碼打包進(jìn)Android Apk包中,可以通過(guò)如下命令:

react-native bundle --platform android --dev false --entry-file index.js --bundle-output RNHybridAndroid/app/src/main/assets/index.android.bundle --assets-dest RNHybridAndroid/app/src/main/res/

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

  • --platform android:代表打包導(dǎo)出的平臺(tái)為Android;
  • --dev false:代表關(guān)閉JS的開發(fā)者模式;
  • -entry-file index.js:代表js的入口文件為index.js
  • --bundle-output:后面跟的是打包后將JS bundle包導(dǎo)出到的位置;
  • --assets-dest:后面跟的是打包后的一些資源文件導(dǎo)出到的位置;

提示:JS bundle一定要正確放到你的Android言語(yǔ)的assets目錄下這個(gè)和我們上文中配置的setBundleAssetName("index.android.bundle")進(jìn)行對(duì)應(yīng)。

發(fā)布應(yīng)用

通過(guò)上述步驟我們完成了將RN代碼打包并生成JS bundle,并放到了assets目錄下,接下來(lái)我們就可以來(lái)通過(guò)Android Studio或者命令的方式來(lái)release我們的RN混合Android應(yīng)用了。

我在之前發(fā)表過(guò)React Native發(fā)布APP之簽名打包APK的博文,
需要的同學(xué)可以去看一下,在這篇文章中就不在重復(fù)了。

更多React Native混合開發(fā)的實(shí)用技巧,可學(xué)習(xí)與此文章配套的視頻課程:《React Native與Android 混合開發(fā)講解》

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,269評(píng)論 25 708
  • 小七,出生在一個(gè)普通平凡的農(nóng)村家庭,父親給予她很大的期望,平時(shí)各方面一直管的很嚴(yán),因此小七一直在強(qiáng)大的壓力下學(xué)習(xí)和...
    茜茜茜是xi不是qian閱讀 597評(píng)論 0 0
  • 1.配置 2.初始化 3.提交 4.對(duì)比 5.版本回退 5.撤銷修改 6.刪除 7.關(guān)聯(lián)遠(yuǎn)程倉(cāng)庫(kù)并提交 8.創(chuàng)建與...
    南風(fēng)nanfeng閱讀 251評(píng)論 0 0
  • 2017年5月11日 天氣多云轉(zhuǎn)晴星期四 今天因?yàn)樘α?,沒(méi)有去接女兒,店里來(lái)人了,沒(méi)有人看兒子,所...
    陌上清歌的簡(jiǎn)書閱讀 125評(píng)論 0 0
  • var setting = { //節(jié)點(diǎn)是否顯示checkbox check:{//是否顯示checkbox en...
    麥子_FE閱讀 1,489評(píng)論 0 1