一個C#開發者用Java搭建Android框架的心路歷程

kiba518發表於2021-11-01

前言

Java框架實在是太多了,因為是初學乍練,所以,只好以百度為標準選擇框架了。

Java的框架文章太難寫了,因為他引用了太多框架,而沒一個框架都有很繁瑣的配置,把每個框架都寫一遍,就等於寫書了;所以本文只能大體上介紹,但大體上介紹,感覺讀起來又沒有生氣,總之非常難寫。

新建專案

首先新建專案KibaFramework,不要勾選use legacy android.support libraries。

專案結構

資料庫:xUtils3,這裡只使用xutils3來管理sqlite資料庫。

頁面元素獲取:butterknife,dataBinding,主要使用butterknife;dataBinding只是提供一種額外的元素獲取模式。

UI框架:XUI、XPage,這個框架的模式非常好,因為是一個人寫的,比一個團隊寫的組合功能更合理,還有demo可以參考。

輔助語言:Kotlin,我覺得Kotlin中的很多語法很好用,很簡便,比如定義實體就非常好用,在大方向使用Java的情況下,輔助使用Kotlin定義一些單獨的檔案,很方便。

專案配置

build.gradle—Project

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
​
​
    ext.kotlin_version = "1.5.0"
    ext.anko_version = "0.10.8"
​
    repositories {
        google()
        mavenCentral()
        jcenter()
        maven { url "https://jitpack.io"}
​
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.2.1"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
​
allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
        maven { url 'https://jitpack.io' }
    }
}
​
task clean(type: Delete) {
    delete rootProject.buildDir
}

build.gradl—App

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}
​
android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"
​
    defaultConfig {
        applicationId "com.vanpeng.survey"
        minSdkVersion 24
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        ndk{
            abiFilters "armeabi-v7a"
        }
​
​
​
    }
​
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        viewBinding true
    }
}
​
dependencies {
​
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.annotation:annotation:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
    implementation 'de.gerdi-project:GSON:6.0.6'
    implementation 'androidx.navigation:navigation-fragment:2.3.0'
    implementation 'androidx.navigation:navigation-ui:2.3.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
​
​
​
    implementation "org.jetbrains.anko:anko-commons:$anko_version"   // Anko Commons
    implementation "org.jetbrains.anko:anko-sdk25:$anko_version" // Anko Layouts sdk15, sdk19, sdk21, sdk23 are also available
    implementation "org.jetbrains.anko:anko-sdk25-coroutines:$anko_version"  // Coroutine listeners for Anko Layouts
    implementation "org.jetbrains.anko:anko-sqlite:$anko_version"   // Anko SQLite
    
    implementation 'org.xutils:xutils:3.3.36'
    implementation "com.squareup.okhttp3:okhttp:4.9.0"
    implementation 'com.google.code.gson:gson:2.8.6'
​
    //解決超過65546程式碼的問題
    implementation 'com.android.support:multidex:1.0.2'
    implementation "com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4"
​
    implementation 'com.jakewharton:butterknife:10.2.3'
    //ButterKnife
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
    //XUI框架
    implementation 'com.github.xuexiangjys:XUI:1.1.8'
​
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'com.github.bumptech.glide:glide:4.11.0'
​
    //工具類
    implementation 'com.github.xuexiangjys.XUtil:xutil-core:2.0.0'
    implementation 'com.github.xuexiangjys.XUtil:xutil-sub:2.0.0'
    //側邊欄選單
    implementation 'com.yarolegovich:sliding-root-nav:1.1.1'
    //下拉重新整理
    implementation 'com.scwang.smart:refresh-layout-kernel:2.0.3'      //核心必須依賴
    implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-header:1.1.5'
    implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-layout:1.1.5'
    //預載入佔位控制元件
    implementation 'me.samlss:broccoli:1.0.0'
    //XPage頁面框架
    implementation 'com.github.xuexiangjys.XPage:xpage-lib:3.1.1'
    annotationProcessor 'com.github.xuexiangjys.XPage:xpage-compiler:3.3.0'
    //如果是androidx專案,使用1.1.0版本及以上
    implementation 'com.github.xuexiangjys.XAOP:xaop-runtime:1.1.0'
​
}

gradle.properties

org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
kotlin.code.style=official
android.enableJetifier=true

專案編寫

首先編寫BaseActivity和BaseFragment,分別繼承XUI和XPage下的XPageActivity和XPageFragment。

然後編寫一些常用的函式在,比如彈出對話方塊。

然後編寫MyApplication,在MyApplication裡注入Xui和xUnit。

XUI.init(this); //初始化UI框架
XUI.debug(true);  //開啟UI框架除錯日誌
x.Ext.init(this);
x.Ext.setDebug(BuildConfig.DEBUG); // 開啟debug會影響效能

然後在配置一些靜態屬性,比如要請求的Api的網址。

最後封裝一些常用的工具類,就可以開發編寫Activity了。

SplashActivity:初始啟動頁面,進行一個漸變的動畫展示,然後通過xUint初始化資料庫,然後跳轉到登入頁面。

LoginActivity:登入頁面,通過Http通訊傳送登入請求。

MainActivity:首頁,實現一個左側滑動選單,和一個fragment的切換內容頁。

編寫完Activity後,在manifest裡增加許可權,並且手動加Activity,因為要設定它的launchMode和其他屬性。

manifest如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kiba.framework">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <application
        android:name=".MyApplication"
        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/Theme.Framework">
        <activity
            android:name=".activity.main.MainActivity"
            android:label="主頁"
            android:screenOrientation="landscape"
            android:launchMode="singleTask"
            android:theme="@style/Theme.Framework.NoActionBar"></activity>
        <activity
            android:name=".activity.protocol.ProtocolActivity"
            android:label="協議內容"
            android:screenOrientation="landscape"
            android:launchMode="singleTask" />
        <activity
            android:name=".activity.login.LoginActivity"
            android:label="登入"
            android:screenOrientation="landscape"
            android:launchMode="singleTask"
            android:theme="@style/Theme.Framework.NoActionBar" />
        <activity
            android:name=".SplashActivity"
            android:label="@string/app_name"
            android:screenOrientation="landscape"
            android:launchMode="singleTask"
            android:theme="@style/Theme.Framework.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
​
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
​
</manifest>

修改themes.xml,注意要讓Theme.Framework繼承XUITheme.Phone,不然將無法解析XUI框架裡自定義屬性的預設值。

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.Framework" parent="XUITheme.Phone">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryVariant">@color/movebule</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
​
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    <style name="Theme.Framework.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
​
    <style name="Theme.Framework.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
​
    <style name="Theme.Framework.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
​
</resources>
關於頁面樣式

頁面樣式我也不擅長,所以這裡基本上以複製開源專案的樣式為主。

登入介面效果:

主頁面效果圖

XUI簡單介紹

XUI是一個非常好用的框架,他重新封裝了Activity和Fragment,讓整體的程式碼邏輯更合理了。

使用時,我們可以讓BaseActivity和BaseFragment繼承XPageActivity和XPageFragment,需要注意的是BaseActivity和BaseFragment需要為抽象類,程式碼如下:

BaseActivity
public class BaseActivity extends XPageActivity {
    //返回值【/storage/emulated/0/Android/data/com.kiba.framework/files】
    public String FilesPath_External; 
    //返回值【/storage/emulated/0】
    public String FilesPath_Internal;
    public Context baseContext; 
    public DbManager.DaoConfig daoConfig;
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        FilesPath_External = getExternalFilesDir("").getAbsolutePath();
        FilesPath_Internal  = Environment.getExternalStorageDirectory().getPath();
        super.onCreate(savedInstanceState); 
        baseContext = this;
        MyApplication.activityList.add(this);
    }  
}
BaseFragment
public abstract class BaseFragment extends XPageFragment {
    
    //返回值【/storage/emulated/0/Android/data/com.kiba.framework/files】
    public String FilesPath_External;
​
    //返回值【/storage/emulated/0】
    public String FilesPath_Internal;
    @Override
    protected void initPage() {
        FilesPath_External = this.getActivity().getExternalFilesDir("").getAbsolutePath();
        FilesPath_Internal  = Environment.getExternalStorageDirectory().getPath();
       
    } 
} 

繼承的Activity需要繼承getLayoutId和onCreate,程式碼如下:

public class LoginActivity extends BaseActivity {
 
    //XUI的繫結頁面的模式
    @Override
    protected int getLayoutId() {
        return R.layout.activity_login;
    }
​
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ButterKnife.bind(this);
    }
 }

繼承的Fragment需要過載getLayoutId和initViews,需要在類上加@Page註解,程式碼如下:

@Page(name = "其他")
public class OtherFragment extends BaseFragment {
​
    @Override
    protected int getLayoutId() {
        return R.layout.fragment_other;
    }
​
    @Override
    protected void initViews() {
        TitleBar titleBar = super.initTitle();
​
    } 
}

我們也可以不過載getLayoutId,自己在onCreate或中initViews中找檢視填充。

final View view = View.inflate(this, R.layout.activity_splash, null);
setContentView(view);

結語

Java的框架真的實在是太多了,而且每一個的內容真都很多,這真的是一個需要大量時間熟悉和學習的語言。

需要學習Java基礎的可以參考一下我的Java短篇文章

Java的委託

Java中的Class類

通過Gson解析Json資料

OKhttp3的使用教程

xUtils3的使用教程

Java泛型詳解

Android DataBinding使用詳解

NavigationView使用簡介

RecyclerView使用詳解

本文主要程式碼來自於開源框架XUI的Demo。

https://github.com/xuexiangjys/XUI

 

----------------------------------------------------------------------------------------------------

到此,使Android框架就已經介紹完了。

程式碼已經傳到Github上了,歡迎大家下載。

Github地址:https://github.com/kiba518/AndroidFramework

----------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------

注:此文章為原創,任何形式的轉載都請聯絡作者獲得授權並註明出處!
若您覺得這篇文章還不錯,請點選下方的推薦】,非常感謝!

https://www.cnblogs.com/kiba/p/15480140.html

 

 

相關文章