主頁 > 移動端開發 > 【12】Kotlin函式泛型協程

【12】Kotlin函式泛型協程

2021-06-09 22:32:18 移動端開發

(1)一個人只要自己不放棄自己,整個世界也不會放棄你.
(2)天生我才必有大用
(3)不能忍受學習之苦就一定要忍受生活之苦,這是多么痛苦而深刻的領悟.
(4)做難事必有所得
(5)精神乃真正的刀鋒
(6)戰勝對手有兩次,第一次在內心中.
(7)好好活就是做有意義的事情.
(8)亡羊補牢,為時未晚
(9)科技領域,沒有捷徑與投機取巧,
(10)有實力,一年365天都是應聘的旺季,沒實力,天天都是應聘的淡季,
(11)基礎不牢,地動天搖
(12)寫博客初心:成長自己,輔助他人,當某一天離開人世,希望博客中的思想還能幫人指引方向.
(13)撰寫實屬不易,若喜歡或者對你有幫助記得點贊+關注或者收藏哦~

【12】Kotlin函式泛型與協程

文章目錄

  • 【12】Kotlin函式泛型與協程
    • 1.專案增加WebView模塊
    • 2.高階函式續
      • 2.1普通函式中定義高階函式
        • 2.1.1定義
        • 2.2使用
      • 2.2函式引數有默認值
      • 2.3高階函式一個形參
      • 2.4高階函式兩個形參
      • 2.5由一個函式直接完成另一個函式的業務操作
      • 2.6高階函式三數相乘
      • 2.7給泛型增加擴展型別
      • 2.8鏈式呼叫
      • 2.9擴展函式高階函式有引數
      • 2.10執行自定義執行緒
      • 2.11自定義輪循器
    • 3.專案代碼優化
    • 4.Kotlin泛型
      • 4.1泛型的讀取模式
      • 4.2泛型的上限與下限
      • 4.3泛型場景1可修改不能獲取
      • 4.4泛型場景2不可修改能獲取
      • 4.5Kotlin泛型與java泛型對應關系
      • 4.6 in out關鍵字實作權限的讀取模式
      • 4.7限定類只能修改不能讀取
      • 4.8限定類可以獲取,不能修改
    • 5.協程使用篇
      • 5.1執行緒環境到協程環境的切換
      • 5.2不使用協程更新UI
      • 5.3使用協程更新UI
      • 5.4阻塞式協程切換執行緒
      • 5.5非阻塞式協程切換執行緒
      • 5.6協程與執行緒的概念
      • 5.7自主學習協程
      • 5.8Rxjava的執行緒切換
      • 5.9協程跟隨main執行緒的結束而結束
      • 5.10阻塞式與非阻塞式協程混合
      • 5.11結束協程
    • 6.打賞鼓勵
      • 6.1微信打賞
      • 6.2支付寶打賞

1.專案增加WebView模塊

package com.gdc.kotlinproject

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.WebSettings
import com.gdc.kotlinproject.config.Flag
import kotlinx.android.synthetic.main.activity_detail_link.*

class DetailLinkActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_detail_link)

        //1.隱藏ActionBar
        supportActionBar?.hide()
        //2.獲取上個頁面傳遞過來的url
        val mUrl: String? = intent.getStringExtra(Flag.URL_KEY)

        //3.設定WebView的一些引數
        //(1)獲取WebView引數設定
        val mWebSettings:WebSettings = web_view.settings
        //(2)將圖片調整到適合webview的大小
        mWebSettings.useWideViewPort = false
        //(3)支持js
        mWebSettings.javaScriptEnabled = true
        //(4)支持自動加載圖片
        mWebSettings.loadsImagesAutomatically = true
        /*
         *(5)利用WebView直接加載網頁鏈接
         * - 每次啟動這個activity 所加載的url網頁路徑肯定是不一樣的 , Intent傳值
         * - ?.意思是這個引數可以為空,并且程式繼續運行下去
         * - !!.的意思是這個引數如果為空,就拋出例外
         */
        web_view.loadUrl(mUrl!!)

    }
}

2.高階函式續

2.1普通函式中定義高階函式

2.1.1定義

/**
 * 1.普通函式中定義高階函式
 * (1)一個引數無回傳
 * myMethod:(String)-> Unit
 */
fun show1(name:String,myMethod:(String)-> Unit){
    myMethod(name)
}

2.2使用

fun main() {
    //1.呼叫方式1
    show1("Derry"){
        println("輸出1:$it")
    }

    //1.呼叫方式2
    show1("張華",myMethod={
        println("輸出2:$it")
    })

    //1.呼叫方式3
    show1("楊紅",{
        println("輸出3:$it")
    })
}

2.2函式引數有默認值

fun show2(name:String="李連杰",myMethod:(String)-> Unit){
    myMethod(name)
}
//1.呼叫有默認值的
    show2{
        println("輸出4:$it")
    }

2.3高階函式一個形參

fun sum1(myMethod:(Int) -> Unit){
    myMethod(11)
}
	sum1 {
        println("輸出5:$it")
    }

    sum1 ({
        println("輸出6:$it")
    })

2.4高階函式兩個形參

fun sum2(myMethod:(Int,Boolean) -> Unit){
    myMethod(11,true)
}
	/**
     * 1.兩個引數就沒法默認it
     * (1)需要手動指定引數名
     * (2)只有一個引數時就是默認的it
     */

    sum2({
        n1,b1->
    })

2.5由一個函式直接完成另一個函式的業務操作

/**
 * 1.高階函式
 */
fun thread01(myMethod:(Int) -> String){
    var ret = myMethod(99)
    println(ret)
}
/**
 * 1.將Int轉換為String型別
 */
fun run01(number:Int):String = "OK $number"
fun main() {
    //以前是在{}里面直接做業務操作
    thread01() {
        ""
    }

    /**
     * 1.組合使用函式
     * (1)::run01的結果拿過來使用,意思是直接交給run01去完成thread01的業務操作
     * (2)將run01變成函式型別的物件將給thread01函式
     */
    thread01(::run01)
}
    //將run01變成函式型別的物件將給thread01函式
    val r01 = ::run01
    var r02 = r01
    thread01(r01)
    thread01(r02)

2.6高階函式三數相乘

/**
 * 1.三數相乘
 * (1)高階函式回傳一個泛型
 * myMethod:(Int,Int,Int)-> R
 *
 * (2)函式也回傳一個泛型
 */
fun <R> sum(n1:Int,n2:Int,n3:Int,myMethod:(Int,Int,Int)-> R):R{
    return myMethod(n1,n2,n3)
}
fun main() {
    //Unit
    //String
    //Boolean
    //Double
    var ret = sum(10,20,30){
        i1,i2,i3 ->
        println("i1:$i1,i2:$i2,i3:$i3")
        //其他操作
        "Ok"
        true
        9999.3
    }

    println(ret)
}

2.7給泛型增加擴展型別

val name = "張三"
val age = 24
val sex = 'M'

fun main() {
    name.myApply()
    age.myApply()
    sex.myApply()
    func().myApply()
}

fun func(){

}

在這里插入圖片描述

/**
 * (1)回傳型別泛型
 * (2)給泛型增加擴展函式
 * (3)意味著類中的屬性、函式都可以使用擴展函式
 */
fun <T> T.myApply(){

}

2.8鏈式呼叫

/**
 * (1)回傳型別泛型
 * (2)給泛型增加擴展函式
 * (3)意味著類中的屬性、函式都可以使用擴展函式
 * (4)無參的高階函式
 */
fun <T> T.myApply1(myMethod:() ->Unit):T{
    //T:就是this
    myMethod()
    return this
}
    /**
     * 鏈式呼叫
     */
    val length = name.myApply1 {

    }.myApply1() {

    }.myApply1() {

    }.length as Double

2.9擴展函式高階函式有引數

/**
 * (1)擴展函式
 * (2)回傳型別泛型
 * (3)高階函式有引數無回傳值
 * myMethod:(T) -> Unit
 * (4)it == T == this
 */
fun <T> T.myAlso(myMethod:(T) -> Unit):T{
    //it == T == this==name
    myMethod(this)
    return this
}
val d = name.myAlso {
        it.length
        println("ret:$it")
    }.myAlso {
        it.length
    }.myAlso {
        it.length
    }.length as Double
/**
 * (1)回傳值泛型R
 * (2)高階函式回傳泛型R
 * myMethod: (T) -> R
 */
fun <T,R> T.myLet(myMethod: (T) -> R):R = myMethod(this)

2.10執行自定義執行緒

/**
 * 1.自定義執行緒封裝
 * (1)start:是否啟動標識
 * (2)name:執行緒名稱
 * (3)myMethod高階函式
 * (4)回傳執行緒
 * (5)如果啟動執行緒就直接啟動,不啟動,則回傳執行緒物件
 */
fun ktrun(
        start:Boolean = true,
        name:String ? = null,
        myMethod:() -> Unit):Thread{
    val thread = object :Thread(){
        override fun run() {
            super.run()

            myMethod()
        }
    }

    name?: "myThread1"

    if(start){
        thread.start()
    }
    return thread
}
fun main() {
    ktrun(){
        //1.耗時操作
        println("如果設定了啟動執行緒,則執行自定義執行緒")
    }
}

2.11自定義輪循器

/**
 * 自定義輪循器,傳入多少次就跌代多少次
 */
fun doCounts(counts:Int,myMethod:(Int) -> Unit){
    //0-counts區間
    for(index in 0 until counts){
        myMethod(index)
    }
}
 	doCounts(100){
        println("執行了一次下標是:$it")
    }

3.專案代碼優化

/**
 * (1)回傳型別泛型
 * (2)給泛型增加擴展函式
 * (3)意味著類中的屬性、函式都可以使用擴展函式
 * (4)無參的高階函式
 */
fun <T> T.myApply(myMethod:T.() ->Unit):T{
    //T:就是this
    myMethod()
    return this
}
	/**
     * 優化之前的代碼
     * 1.創建客戶端API介面
     * (1)WanAndroidAPI實體化
     * (2)XXXAPI實體化
     * (3)動態的實體化,可以使用到泛型
     * (4)fun <T> instanceRetrofit(apiInterface: Class<T>): T表示此為泛型方法
     * (5)apiInterface: Class<T>:表示此為泛型引數
     * (6): T表示回傳型別為泛型
     */
    /*fun <T> instanceRetrofit(apiInterface: Class<T>) : T{

        //1.1.1OKHttpClient請求服務器
        val okHttpclient = OkHttpClient().newBuilder()
        //1.1.1.1添加讀取超時時間
            .readTimeout(10000, TimeUnit.SECONDS)
        //1.1.1.2添加連接超時時間
            .connectTimeout(10000,TimeUnit.SECONDS)
        //1.1.1.3添加寫出超時時間
            .writeTimeout(10000,TimeUnit.SECONDS)
            .build()

        val retrofit:Retrofit = Retrofit.Builder()
            //1.1請求方 <-
            .baseUrl(Flag.BASE_URL)
            .client(okHttpclient)

            //1.2回應方 ->
            //1.2.1RxJava來處理
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            //1.2.2Gson來決議JavaBean
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        //1.3將請求方與回應方建好后,將請求api的引數
        return retrofit.create(apiInterface)
    }*/


    //優化后的代碼
    fun <T> instanceRetrofit(apiInterface: Class<T>) : T{

        //1.1.1OKHttpClient請求服務器
        val okHttpclient = OkHttpClient().newBuilder().myApply {
            //1.1.1.1添加讀取超時時間
            readTimeout(10000, TimeUnit.SECONDS)
            //1.1.1.2添加連接超時時間
            connectTimeout(10000,TimeUnit.SECONDS)
            //1.1.1.3添加寫出超時時間
            writeTimeout(10000,TimeUnit.SECONDS)
        }.build()


        val retrofit:Retrofit = Retrofit.Builder()
            //1.1請求方 <-
            .baseUrl(Flag.BASE_URL)
            .client(okHttpclient)

            //1.2回應方 ->
            //1.2.1RxJava來處理
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            //1.2.2Gson來決議JavaBean
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        //1.3將請求方與回應方建好后,將請求api的引數
        return retrofit.create(apiInterface)
    }

4.Kotlin泛型

(1)?是java泛型通配符
(2)*是Kotlin的通配符
(3)Kotlin簡單平常的泛型與Java是一樣的,
(4)泛型不一樣的地方是out與in

4.1泛型的讀取模式

private ParentClass parentClass = new ParentClass();
    
    private ChildClass childClass = new ChildClass();

    /**
     * 泛型的讀取模式
     */
    public void test01(){

        //(1)想實作這種多型,java是不支持的,使用權限模式解決
        //List<ParentClass> list = new ArrayList<ChildClass>();

        //(2)解決問題 ? extends ParentClass :權限獲取模式,只能獲取,不能修改
        List<? extends ParentClass> list = new ArrayList<ChildClass>();

        //(3)不能添加,不能對集合做修改操作
        //list.add(parentClass);
        //list.add(null);是特殊情況

        //(4)能獲取
       ParentClass p = list.get(0);


        /**
         * (5)只能修改,不能獲取的情況
         * ? super ChildClass,只能修改,不能獲取
         */
        List<? super ChildClass> childList = new ArrayList<ParentClass>();

        //(6)能添加但是不能獲取
        childList.add(childClass);

        //(7)不能獲取
        //ChildClass c = childList.get(0);
    }

4.2泛型的上限與下限

public class TestOutIn<T extends String> {

4.3泛型場景1可修改不能獲取

	private void show(List<? extends ParentClass> list){
        //(1)能獲取
        list.get(0);
        for (ParentClass p : list){

        }
        
        //(2)不能修改
        //list.add(parentClass);
    }

    private void test2(){
        List<ChildClass> childList = new ArrayList<ChildClass>();
        //(1)show方法要求是傳父類,而此處傳子類,就可以修改泛型的引數
        show(childList);
    }

4.4泛型場景2不可修改能獲取

	/**
     * (1)不可以獲取
     * (2)可以修改
     * @param list
     */
    private void show1(List<? super ChildClass> list){
        //ChildClass c = list.get(0);
        /*for(ChildClass c : list){

        }*/

        list.add(childClass);
    }

    private void test3(){
        List<ParentClass> parentList = new ArrayList<ParentClass>();
        //(1)show1方法要求是傳子類,但此處傳的是父類,可以修改泛型引數
        show1(parentList);
    }

4.5Kotlin泛型與java泛型對應關系

在這里插入圖片描述

4.6 in out關鍵字實作權限的讀取模式

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlin.generic.ktoutin
 * @file
 * @Description:
 *
 * 1.權限的讀取模式
 *
 * @date 2021-6-6 20:53
 * @since appVer
 */

val parentClass = ParentClass()

val childClass = ChildClass()

fun test01(){
    /**
     * 1.out 只能讀取,不能修改
     *(1)同Java
     * List<? extends ParentClass> list = new ArrayList<ChildClass>();
     */
    val list : MutableList<out ParentClass> = ArrayList<ChildClass>()

    /**
     * 2.in 不能讀取,只能修改
     * (1)同Java
     *  List<? super ChildClass> childList = new ArrayList<ParentClass>();
     */
    val list1 : MutableList<in ChildClass> = ArrayList<ParentClass>()
}

4.7限定類只能修改不能讀取

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlin.generic.ktobj
 * @file
 * @Description:
 * 1.泛型的讀取模式
 *
 * (1)Student <in T>:限定該類只能修改不能讀取
 *
 * (2)為了解決多個函式都需要添加泛型讀取模式限定,可以直接在類上做限定,一勞永逸
 *
 * 而Java是做不到的
 *
 * @date 2021-6-6 21:31
 * @since appVer
 */ 
class Student <in T> {

    fun a1(list:T){

    }

   /* fun a2(list:MutableList<in T>){

    }

    fun a3(list:MutableList<in T>){

    }

    fun a4(list:MutableList<in T>){

    }

    fun a5(list:MutableList<in T>){

    }

    fun a6(list:MutableList<in T>){

    }*/

    /**
     * 如此限定的好處
     */
    fun setData(data : T){

    }

    /**
     * 不能從此類獲取資料
     */
    /*fun getData() : T{

    }*/

}

4.8限定類可以獲取,不能修改

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlin.generic.ktobj
 * @file
 * @Description:
 *
 * (1)限定類可以獲取,不能修改
 *
 * @date 2021-6-6 21:42
 * @since appVer
 */
class Teacher<out T> {

    /**
     * 1.能獲取
     */
    fun getData() : T? = null

    /**
     * 2.不能修改
     */
    /*fun setData(data:T){

    }*/
}

5.協程使用篇

5.1執行緒環境到協程環境的切換

在這里插入圖片描述

    fun click1(view: View) = runBlocking{

        /**
         * (1)由main執行緒切換到協程環境,默認是main執行緒
         * (2)runBlocking切換到的是外協程
         * (3)launch切換到的是內協程
         * (4)由main執行緒變為異步執行緒
         * aunch(Dispatchers.IO)
         * (5)輪循
         *
         */
        launch(Dispatchers.IO) {
            Log.e("click1:","lunch ${Thread.currentThread().name}")

            repeat(10){
                Thread.sleep(1000)
                Log.e("click:","計數中:${it}")
            }
        }
    }

5.2不使用協程更新UI

private val mOkHttpClient : OkHttpClient = OkHttpClient()
private val mRequest = Request.Builder().url("http://www.baidu.com").get().build()

fun displayMethod(textView:TextView){

    /**
     * 切換為主執行緒更新UI
     */
    val han = Handler(Looper.getMainLooper()){
        textView.text = it.obj as String
        false
    }

    /**
     * 1.異步執行緒
     */
    object : Thread(){
        override fun run() {
            super.run()
            val result = mOkHttpClient.newCall(mRequest).execute().body()?.string()
            val msg = han.obtainMessage()
            msg.obj = result
            han.sendMessage(msg)
        }
    }.start()
}
fun click2(view: View) = runBlocking{
        /**
         * 1.不使用協程,更新UI
         */
        //displayMethod(textView)

        /**
         * 2.使用協程,更新UI
         */
        displayMethodXC(textView)
    }

5.3使用協程更新UI

/**
 * 使用協程更新UI
 */
fun displayMethodXC(textView:TextView) = runBlocking{

    /*launch {
        val def = async(Dispatchers.IO) {
            //1.異步執行緒
            true

            "String"

            //2.不考慮例外的情況

            mOkHttpClient.newCall(mRequest).execute().body()?.string()
        }

        *//**
         * 3.main
         * 可以拿到異步執行后的結果
         *//*
        textView.text = def.await()
    }*/

    /**
     * 簡化寫法
     */
    launch {
        //協程外部是主執行緒
        textView.text = async(Dispatchers.IO) {
            //異步執行緒
            mOkHttpClient.newCall(mRequest).execute().body()?.string()
        }.await()
    }

5.4阻塞式協程切換執行緒

/**
     * 1.完成這種  異步執行緒  和  主執行緒  的切換,這個需求:之前我們用RxJava實作過了
     *
     * (1)注冊耗時操作
     * (2)注冊耗時操作完成后,更新注冊UI
     * (3)登錄耗時操作
     * (4)登錄耗時操作完成后,更新登錄UI
     *
     * 2.這種方式是阻塞式的
     * 加載框只有等所有操作執行完成后才能顯示
     */
    fun click3(view: View) = runBlocking{
        launch {
            val pro = ProgressDialog(this@XcActivity)
            pro.setMessage("正在執行中...")
            pro.show()

            //1.注冊耗時操作  異步
            withContext(Dispatchers.IO){
                Log.d("click3", "1.注冊耗時操作: ${Thread.currentThread().name}")
                Thread.sleep(2000)
            }

            // 2.注冊耗時操作完成后,更新注冊UI  main
            Log.d("click3", "2.注冊耗時操作完成后,更新注冊UI: ${Thread.currentThread().name}")

            // 3.登錄耗時操作  異步
            withContext(Dispatchers.IO) {
                Log.d("click3", "3.登錄耗時操作: ${Thread.currentThread().name}")
                Thread.sleep(3000)
            }

            // 4.登錄耗時操作完成后,更新登錄UI
            Log.d("click3", "4.登錄耗時操作完成后,更新登錄UI: ${Thread.currentThread().name}")

        }
    }

5.5非阻塞式協程切換執行緒

/**
     * 1.完成這種  異步執行緒  和  主執行緒  的切換,這個需求:之前我們用RxJava實作過了
     *
     * (1)注冊耗時操作
     * (2)注冊耗時操作完成后,更新注冊UI
     * (3)登錄耗時操作
     * (4)登錄耗時操作完成后,更新登錄UI
     *
     * 2.非阻塞式協程
     */
    fun click4(view: View) = runBlocking{
        GlobalScope.launch(Dispatchers.Main) {

            val pro = ProgressDialog(this@XcActivity)
            pro.setMessage("正在執行中...")
            pro.show()

            //1.注冊耗時操作  異步
            withContext(Dispatchers.IO){
                Log.d("click4", "1.注冊耗時操作: ${Thread.currentThread().name}")
                Thread.sleep(2000)
            }

            // 2.注冊耗時操作完成后,更新注冊UI  main
            Log.d("click4", "2.注冊耗時操作完成后,更新注冊UI: ${Thread.currentThread().name}")

            // 3.登錄耗時操作  異步
            withContext(Dispatchers.IO) {
                Log.d("click4", "3.登錄耗時操作: ${Thread.currentThread().name}")
                Thread.sleep(3000)
            }

            // 4.登錄耗時操作完成后,更新登錄UI
            Log.d("click3", "4.登錄耗時操作完成后,更新登錄UI: ${Thread.currentThread().name}")

            pro.dismiss()
        }
    }

5.6協程與執行緒的概念

(1)執行緒

  • 是通過作業系統調度的
  • 依附于行程,在行程角度看,執行緒是輕量級的
  • 創建10000個執行緒,作業系統崩潰,記憶體溢位

(2)協程:

  • 更多是讓用戶來控制
  • 在執行緒角度看,協程是更輕量級的
  • 創建10000個執行緒,作業系統不會崩潰,更多是由代碼控制

5.7自主學習協程

【協程電子書】

5.8Rxjava的執行緒切換

(1)比執行緒切換更加的方便

5.9協程跟隨main執行緒的結束而結束

fun main() {
    /**
     * 1.非阻塞式協程:類似于守護執行緒
     * (1)協程會跟隨main執行緒的結束而結束
     */
    GlobalScope.launch {

        delay(1000)
        println("中華人民共和國")
    }

    println("A")

    /**
     * main執行緒睡眠2秒
     */
    //Thread.sleep(2000)

    Thread.sleep(200)

    println("B")

    //main結束
}

5.10阻塞式與非阻塞式協程混合

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.knowledge.kotlin.xc
 * @file
 * @Description:
 * 1.執行緒切換為阻塞式協程當中
 * (1)阻塞我們的執行
 * @date 2021-6-6 23:27
 * @since appVer
 */
fun main():Unit = runBlocking{//1.外協程

	//非阻塞式執行
    GlobalScope.launch {//2.內協程
        delay(1000)
        println("中華人民共和國")
    }

    //阻塞式執行的
    println("A")

    //阻塞式執行的
    delay(2000)

    //阻塞式執行的
    println("B")

    //main結束
}

5.11結束協程

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.knowledge.kotlin.xc
 * @file
 * @Description:
 * 1.結束協程
 * 2.suspend執行緒掛起函式標記
 * @date 2021-6-6 23:34
 * @since appVer
 */
suspend fun main() {

   val job = GlobalScope.launch {

        repeat(100){
            delay(20)
            println("中華人民共和國$it")
        }
    }

    println("A")

    /**
     * 只等待100毫秒,時間到結束協程
     */
    Thread.sleep(100)

    //面試題:使用job.cancel()可以結束,為什么還要使用cancelAndJoin()函式,主要是有時間差的區別
    //job.cancel()//有一點點的時間差
    job.cancelAndJoin()//一點點時間差,都不允許
}

6.打賞鼓勵

感謝您的細心閱讀,您的鼓勵是我寫作的不竭動力!!!

6.1微信打賞

在這里插入圖片描述

6.2支付寶打賞

在這里插入圖片描述

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

標籤:其他

上一篇:C++中cout的格式使用

下一篇:Android進階知識——Android執行緒和執行緒池

標籤雲
其他(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