主頁 > 移動端開發 > Android MVVM框架搭建(一)ViewModel + LiveData + DataBinding

Android MVVM框架搭建(一)ViewModel + LiveData + DataBinding

2021-10-30 09:54:32 移動端開發

Android MVVM框架搭建(一)ViewModel + LiveData + DataBinding

  • 前言
  • 正文
    • 一、創建專案
    • 二、ViewModel使用
      • ① 系結Activity
      • ② 頁面布局繪制
      • ③ 實作登錄
    • 二、LiveData使用
      • ① 可修改資料
      • ② 資料觀察
    • 三、DataBinding使用
      • ① 單向系結
      • ② 雙向系結
    • 四、原始碼

前言

??MVVM框架出來已經有一段時間了,現在也有很多的專案運用了MVVM框架,因此也不算是很新的東西,但是從個人的角度來說我希望寫出來,因為每年都會有新的Android開發工程師進入,一些框架的使用都是封裝好的,或者寫的很高級,剛開始不容易看懂,因此我的想法是寫一個簡單易懂的MVVM框架,并且在這個上面去加入Jetpack的組件,當然了,我技術比較菜,大佬要是看見了高抬貴手,

正文

??MVVM框架是有由來的,這個其實說來話長了,還得從最開始的Android 視圖、UI來說起,最開始的時候Android撰寫頁面,里面的業務邏輯和UI處理都在Activity中,很符合這樣一個圖,
在這里插入圖片描述

一、創建專案

而最開始的解耦框架是MVC,Model + View + Controller,

??Model (模型層) 保存資料的狀態,比如資料存盤,網路請求,同時還與View 存在一定的耦合,可以通過觀察者模式通知 View 狀態的改變來讓view 更新,

??View (視圖層) 同時回應用戶的互動行為并觸發 Controller 的邏輯,View 還有可能修改Model 的狀態 以使其與 Model 同步,View 還會在model 中注冊 model 事件的改變,以此來重繪自己并展示給用戶,

??Control (控制層)控制器由View 根據用戶行為觸發并回應來自view 的用戶互動,然后根據view 的事件邏輯來修改對應的Model, Control 并不關心 View 如何展示 相關資料或狀態,而是通過修改 Model 來實作view 的資料的重繪,

而中間的框架是MVP,Model + View + Presenter,相當于對MVC框架的進一步升級,解耦,不過也有缺點,額外增加了大量的介面、類,不方便進行管理,所以關于MVP的話就還有一個Contract要去處理,

Contract 如其名,是一個契約,將Model、View、Presenter 進行約束管理,方便后期類的查找、維護,

presenter - 邏輯處理層對UI的各種業務事件進行相應處理,不與View產生直接關系,

最后是我們當前最流行的框架MVVM,Model + View + ViewModel,解耦更徹底,如果說之前是藕斷絲連的話,現在就是一刀兩斷,

ViewModel:關聯層,將Model和View進行系結,只做和業務邏輯相關的作業,不涉及任何和UI相關的操作,不持有控制元件參考,不更新UI,

View只做和UI相關的作業,不涉及任何業務邏輯,不涉及操作資料,不處理資料,UI和資料嚴格的分開,

好了,說了這么多理論的東西,下面進入實操環節,先說明開發環境,我使用的Android Studio是4.2.1,API版本30,gradle 版本6.7.1,JDK8,電腦Win10,

首先創建一個專案,命名為MVVM-Demo,
在這里插入圖片描述
本文的主要目標是ViewModel 和 DataBinding,

??從Google的官方說明來看,ViewModel 類旨在以注重生命周期的方式存盤和管理界面相關的資料,ViewModel 類讓資料可在發生螢屏旋轉等配置更改后繼續留存,DataBinding資料系結庫是一種支持庫,借助該庫,您可以使用宣告性格式(而非程式化地)將布局中的界面組件系結到應用中的資料源,

看懂了之后首先在專案中,啟用DataBinding,找到app模塊下的build.gradle,在android{}閉包下添加如下代碼:

	//啟用DataBinding
    buildFeatures {
        dataBinding true
    }

然后點擊AS右上角的Sync Now進行工程配置同步,而ViewModel不需要做什么就可以使用了,

二、ViewModel使用

??ViewModel的優勢在于生命周期和資料持久化,那么它就適用于Activity和Fragment,其次就是異步回呼,不會造成記憶體泄漏,再次就是對View層和Model層進行隔離,是兩者不存在耦合性,因此你可以知道ViewModel在整個MVVM框架中的重要性了,

① 系結Activity

在MVVM的框架中,每一個Activity都應該對應一個ViewModel,而現在我們有一個MainActivity,因此可以新建一個viewmodels包,包下新建一個MainViewModel類,表示與MainActivity進行系結,

public class MainViewModel extends ViewModel {

}

注意這里要繼承ViewModel,雖然現在里面什么都沒有的,但后面使用的時候會進行增加,下面先將我們的MainActivity與MainViewModel進行系結,

回到MainActivity中,修改代碼如下圖所示;
在這里插入圖片描述
現在我們的MainActivity和MainViewModel就系結起來了,ViewModel是資料持久化的,因為對于一些變數就可以直接放在ViewModel當中,而不再放在Activity中,可以根據一個實際的需求來進行,

② 頁面布局繪制

比如我現在有一個登錄的功能要去實作,要怎么去對資料進行處理呢?

在ViewModel中定義兩個變數

	public String account;
    public String pwd;

賬號和密碼這當然是最基本的兩個資料了,下面我們修改一下activity_main.xml中的布局,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="32dp"
    tools:context=".MainActivity">

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/et_account"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:hint="賬號" />
    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/et_pwd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:hint="密碼"
            android:inputType="textPassword" />
    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.button.MaterialButton
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_margin="24dp"
        android:insetTop="0dp"
        android:insetBottom="0dp"
        android:text="登  錄"
        app:cornerRadius="12dp" />

</LinearLayout>

③ 實作登錄

下面回到MainActivity中,增加代碼如下圖所示:
在這里插入圖片描述
乍一看好像沒啥不同的,無非就是給mainViewModel中的兩個變數賦了值,不過這里有一個資料持久化的內容在里面,怎么證明呢?看一下下面這個GIF圖
在這里插入圖片描述
??這個圖可能有一些黑屏的地方,因為我在給自己的手機做橫豎屏切換的時候,手機錄屏好像有一點問題,不過沒事,因為這個結果是對的,那就是資料持久化,因為我們知道手機在切換螢屏的時候Activity是會重新創建的,因此如果我們的資料是放在Activity中,那么切換螢屏之后就會重置,輸入框也不會有值,但是通過ViewModel去保存輸入框的值就不同了,雖然你的Activity在切換螢屏的時候銷毀并且重新創建了,但是我的MainModel依然穩定,所以我才能在橫屏的時候也登陸,這樣不會造成資料丟失,

二、LiveData使用

??LiveData是用來做什么的?資料變化感知,也就是說如果我一個頁面中對一個TextView進行多次賦值的話,可以通過LiveData來操作,只需要在值改變的時候進行設定就好了,可以簡化頁面上的代碼,下面舉一個實際的例子來說明,依然是之前那個登錄頁面,不過需要修改一下MainViewModel中的變數,如下:

① 可修改資料

	public MutableLiveData<String> account = new MutableLiveData<>();
    public MutableLiveData<String> pwd = new MutableLiveData<>();

??請注意這里使用的是MutableLiveData,表示值的內容開變動,而LiveData是不可變的,<>中的是泛型,你可以直接將一個物件放進去,當物件的內容有改動時,通知改變就可以了,現在這么寫是為了方便理解,下面進入MainActivity中,首先我們改變一下布局activity_main.xml在按鈕的下面再加如下代碼

	<TextView
        android:id="@+id/tv_account"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/tv_pwd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

② 資料觀察

然后回到MainActivity中,修改代碼如下圖所示:

在這里插入圖片描述
??上面的圖中從上往下有四處標注,我們從下面的兩處標注來看,首先在給MainViewModel中的account賦值時,采用了MutableLiveData的setValue()的方式,還有一種方式是postValue(),這里要注意一點setValue()只能在主執行緒中呼叫,postValue()可以在任何執行緒中呼叫,pwd也是一樣的,然后在最后一處標注的地方,對MainViewModel中的account和pwd進行資料觀察,當這兩個值有改變時通知頁面最新的值,這里用了lambda運算式進行了一次簡化,實際的代碼是這樣的,
在這里插入圖片描述
下面我們運行一下:
在這里插入圖片描述

三、DataBinding使用

??Android的DataBinding在已經內置了,因此只需要在app模塊的build.gradle中開啟就可以使用了,DataBinding,顧名思義就是資料系結,可以看到現在的三個組件都與資料有關系,ViewModel資料持有,LiveData資料觀察、DataBinding資料系結,

① 單向系結

??而DataBinding的系結有兩種方式:單向資料系結和雙向資料系結,舉個例子:比如我手機上收到一個通知,我需要顯示通知的文字內容在頁面上,這就是單向系結,而我頁面上的文字內容改變也重新發一個通知出去,這就是雙向系結,可以理解為A和B進行互動,A發訊息,B要做出反應,B發訊息,A也要相應改變,最常用的就是當我Model中的資料改變時,改變頁面上的值,這個是單向系結,下面我們可以新建一個用戶User物件,代碼如下:

public class User extends BaseObservable {

    private String account;
    private String pwd;

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
        notifyChange();//通知改變 所有引數改變
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public User(String account, String pwd) {
        this.account = account;
        this.pwd = pwd;
    }
}

這里我繼承了BaseObservable,注意它在androidx.databinding包下,然后我們的資料是需要顯示在頁面上的,而之前是通過Activity獲取xml中的控制元件,然后顯示資料在控制元件上,而現在有了DataBinding,可以直接和xml的中資料進行系結,這看起來和JS比較像,下面我們對activity_main.xml進行改變,改變后代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <!--系結資料-->
    <data>
        <variable
            name="user"
            type="com.llw.mvvm.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="32dp"
        tools:context=".MainActivity">

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/et_account"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/white"
                android:hint="賬號" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/et_pwd"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/white"
                android:hint="密碼"
                android:inputType="textPassword" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.button.MaterialButton
            android:id="@+id/btn_login"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_margin="24dp"
            android:insetTop="0dp"
            android:insetBottom="0dp"
            android:text="登  錄"
            app:cornerRadius="12dp" />

        <TextView
            android:id="@+id/tv_account"
            android:text="@{user.account}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/tv_pwd"
            android:text="@{user.pwd}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>
</layout>

這里我在最外層加了一個layout標簽,然后將原來的布局放在layout里面,再增加一個資料源,也就是user物件,然后再底部的兩個tv_account和tv_pwd兩個TextView中的text屬性中系結了user物件中的屬性值,當然這樣還沒有完成,最后一步是在MainActivity中去進行系結的,

進入MainActivity,在onCreate方法中,先將其他的代碼注釋掉,
在這里插入圖片描述
然后修改待明日如下圖所示
在這里插入圖片描述

??這里要注意一點,DataBindingUtil.setContentView回傳的是一個ViewDataBinding物件,這個物件的生成取決于你的Activity,例如MainActivity,就會生成ActivityMainBinding,然后再通過生成的ActivityMainBinding去設定要顯示在xml中控制元件的值,因此你會看到我完全沒有去findViewById,然后控制元件再去設定這個setText,還有一點就是當你使用了DataBinding之后就不需要去手動findViewById了,通過編譯時技識訓生成駝峰命名的物件,如上圖的btnLogin、etAccount、etPwd,上圖的代碼就是通過更改資料然后通知到xml做更改,初始化的修改時admin、123456,然后再通過輸入框去修改,我將會輸入study、666,然后點擊登錄按鈕,也會將輸入框的資料顯示在TextView上,這樣是否會省去很多不必要的繁瑣作業呢?下面運行一下:
在這里插入圖片描述

② 雙向系結

??雙向系結是建立在單向系結的基礎上,實際的開發中用到雙向系結的地方并沒有單向系結多,雙向系結舉一個例子,在輸入框輸入資料時候直接將資料源中的資料進行改變,這里會用到ViewModel和LiveData,下面進行雙向系結的使用,修改一下MainViewModel,代碼如下:

public class MainViewModel extends ViewModel {

    public MutableLiveData<User> user;

    public MutableLiveData<User> getUser(){
        if(user == null){
            user = new MutableLiveData<>();
        }
        return user;
    }
}

下面修改User類,這里面做了一些改變

public class User extends BaseObservable {

    public String account;
    public String pwd;

    @Bindable
    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
        notifyPropertyChanged(BR.account);//只通知改變的引數
    }

    @Bindable
    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
        notifyPropertyChanged(BR.pwd);//只通知改變的引數
    }

    public User(String account, String pwd) {
        this.account = account;
        this.pwd = pwd;
    }
}

不同于notifyChange()改變某一個引數,某一個物件都會通知,現在notifyPropertyChanged()就具有針對性,只通知對應屬性改變,之前在activity_main.xml中的data標簽中是使用的User,現在我們改成ViewModel,順便把布局調整一下,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <!--系結資料-->
    <data>
        <variable
            name="viewModel"
            type="com.llw.mvvm.viewmodels.MainViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="32dp"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/tv_account"
            android:text="@{viewModel.user.account}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:layout_marginBottom="24dp"
            android:id="@+id/tv_pwd"
            android:text="@{viewModel.user.pwd}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/et_account"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/white"
                android:text="@={viewModel.user.account}"
                android:hint="賬號" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/et_pwd"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/white"
                android:text="@={viewModel.user.pwd}"
                android:hint="密碼"
                android:inputType="textPassword" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.button.MaterialButton
            android:id="@+id/btn_login"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_margin="24dp"
            android:insetTop="0dp"
            android:insetBottom="0dp"
            android:text="登  錄"
            app:cornerRadius="12dp" />

    </LinearLayout>
</layout>

這里要注意點的地方有幾個,第一個是資料源,這里系結的是ViewModel,那么相對應的ViewModel中的資料資料都可以拿到,
在這里插入圖片描述
第二個就是回應的地方,通過這種方式去顯示ViewModel中物件的變數資料在控制元件上,這里我把這兩個TextView放到輸入框的上方
在這里插入圖片描述
第三個地方,也是雙向系結的意義,就是UI改變資料源,我們都知道當輸入框輸入時,text屬性值會改變為輸入的資料,而@={viewModel.user.account}就是將輸入的資料直接賦值給資料源,這樣在Activity中我們將不需要去進行輸入框的處理,減少了耦合,
在這里插入圖片描述
下面讓我們回到MainActivity中,修改代碼后如下:

private ActivityMainBinding dataBinding;
    private MainViewModel mainViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //資料系結視圖
        dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        mainViewModel = new MainViewModel();
        //Model → View
        User user = new User("admin", "123456");
        mainViewModel.getUser().setValue(user);
        //獲取觀察物件
        MutableLiveData<User> user1 = mainViewModel.getUser();
        user1.observe(this, user2 -> dataBinding.setViewModel(mainViewModel));

        dataBinding.btnLogin.setOnClickListener(v -> {
            if (mainViewModel.user.getValue().getAccount().isEmpty()) {
                Toast.makeText(MainActivity.this, "請輸入賬號", Toast.LENGTH_SHORT).show();
                return;
            }
            if (mainViewModel.user.getValue().getPwd().isEmpty()) {
                Toast.makeText(MainActivity.this, "請輸入密碼", Toast.LENGTH_SHORT).show();
                return;
            }
            Toast.makeText(MainActivity.this, "登錄成功", Toast.LENGTH_SHORT).show();
        });
    }

下面運行一下:
在這里插入圖片描述
我發現我的手機錄屏似乎是出了問題,當點擊第二個輸入框的時候,錄屏中會黑屏,所以這個GIF很短,具體的效果請下載原始碼去運行,

四、原始碼

GitHub:MVVM-Demo

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/341925.html

標籤:其他

上一篇:【Android 逆向】APK 檔案格式 ( Android 應用安裝 | Zip 檔案格式 | 使用 Python 代碼提取 APK 檔案 )

下一篇:Android IPC 之 AIDL 使用

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more