最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android開發(fā)筆記之圖片緩存、手勢(shì)及OOM分析

 更新時(shí)間:2016年01月08日 11:13:14   作者:yh_thu  
這篇文章主要介紹了Android開發(fā)筆記之圖片緩存、手勢(shì)及OOM分析 的相關(guān)資料,需要的朋友可以參考下

把圖片緩存、手勢(shì)及OOM三個(gè)主題放在一起,是因?yàn)樵贏ndroid應(yīng)用開發(fā)過程中,這三個(gè)問題經(jīng)常是聯(lián)系在一起的。首先,預(yù)覽大圖需要支持手勢(shì)縮放,旋轉(zhuǎn),平移等操作;其次,圖片在本地需要進(jìn)行緩存,避免頻繁訪問網(wǎng)絡(luò);最后,圖片(Bitmap)是Android中占用內(nèi)存的大戶,涉及高清大圖等處理時(shí),內(nèi)存占用非常大,稍不謹(jǐn)慎,系統(tǒng)就會(huì)報(bào)OOM錯(cuò)誤。

慶幸的是,這三個(gè)主題在Android開發(fā)中屬于比較普遍的問題,有很多針對(duì)于此的通用的開源解決方案。因此,本文主要說明筆者在開發(fā)過程中用到的一些第三方開源庫(kù)。主要內(nèi)容如下:

1.Universal Image Loader、Picasso、Glide與Fresco的對(duì)比及使用
2.PhotoView、GestureImageView的原理及使用
3.leakcanry內(nèi)存分析工具

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

一、Universal Image Loader、Picasso、Glide與Fresco的對(duì)比及使用

Universal Image Loader(UIL)、Picasso、Glide與Fresco是Android中進(jìn)行圖片加載的常用第三方庫(kù),主要封裝了內(nèi)存緩存、磁盤緩存、網(wǎng)絡(luò)請(qǐng)求緩存、線程池等方法,抽象了圖片加載的流程,很大程度避免了加載圖片引起的內(nèi)存溢出,提高了圖片加載的效率。下圖是筆者近期從各個(gè)庫(kù)的github頁(yè)面查詢到的信息:

 

需要說明的是:

•Imageloader是最早開源的圖片緩存庫(kù),目前作者已停止維護(hù)(11.27);
•Picasso的實(shí)際作者是Square的Jake Wharton,Android領(lǐng)域的絕對(duì)大牛;
•Glide是由Google員工開源的,在Google I/O 2014官方應(yīng)用中推薦使用;
•Fresco的圖片加載不使用Java堆內(nèi)存,而是匿名共享內(nèi)存(Ashmem)。

附上各個(gè)庫(kù)的github地址:

Universal Image Loader:https://github.com/nostra13/Android-Universal-Image-Loader.git

Picasso:https://github.com/square/picasso.git

Glide:https://github.com/bumptech/glide.git

Fresco:https://github.com/facebook/fresco.git

這四個(gè)圖片緩存庫(kù)的基本使用(HelloWorld)都可以通過一句代碼實(shí)現(xiàn),分別如下:

UIL:

ImageLoader.getInstance().displayImage(url, imageView);

Picasso:

Picasso.with(context).load(url).into(imageView);

Glide:

Glide.with(context).load(url).into(imageView);

Fresco:

simpleDraweeView.setImageURI(uri);

細(xì)心的朋友可以看出,Picasso和Glide的API非常類似。事實(shí)上,這四個(gè)庫(kù)在實(shí)現(xiàn)的核心思想上都比較相似,可以抽象為以下五個(gè)模塊:

1.RequestManager,主要負(fù)責(zé)請(qǐng)求生成和管理模塊;
2.Engine,主要負(fù)責(zé)創(chuàng)建任務(wù)以及執(zhí)行調(diào)度;
3.GetDataInterface,獲取數(shù)據(jù)的接口,主要用于從內(nèi)存緩存、磁盤緩存以及網(wǎng)絡(luò)等獲取圖片數(shù)據(jù);
4.Displayer,主要用于顯示圖片,可能是對(duì)ImageView的封裝或者其他虛擬的Displayer;
5.Processor,主要負(fù)責(zé)處理圖片,比如圖片的旋轉(zhuǎn)、壓縮以及截取等操作。

說一句題外話,掌握了各種開源庫(kù)的實(shí)現(xiàn)的核心思想后,會(huì)發(fā)現(xiàn)軟件工程的一個(gè)共同點(diǎn),就是通過將流程形式化、抽象化,從而提高效率。不論是業(yè)務(wù)的效率,還是開發(fā)的效率,這或許也是軟件作為一門科學(xué)的核心思想。

ImageLoader的設(shè)計(jì)及優(yōu)點(diǎn)

ImageLoader加載的流程如下圖。(需要申明:下面三張流程圖來自Trinea,尊重原作者版權(quán))


ImageLoader收到加載及顯示圖片的任務(wù),ImageLoaderEngine分發(fā)任務(wù),獲得圖片數(shù)據(jù)后,BitmapDisplayer 在ImageAware中顯示。

ImageLoader的有點(diǎn):

•支持下載進(jìn)度監(jiān)聽
•可以在 View 滾動(dòng)中暫停圖片加載,通過 PauseOnScrollListener 接口可以在 View 滾動(dòng)中暫停圖片加載。
•默認(rèn)實(shí)現(xiàn)多種內(nèi)存緩存算法,這幾個(gè)圖片緩存都可以配置緩存算法,不過 ImageLoader 默認(rèn)實(shí)現(xiàn)了較多緩存算法,如 Size 最大先刪除、使用最少先刪除、最近最少使用、先進(jìn)先刪除、時(shí)間最長(zhǎng)先刪除等。

•支持本地緩存文件名規(guī)則定義

Picasso的設(shè)計(jì)及優(yōu)點(diǎn)

Picasso的加載流程如下圖:


Picasso收到加載及顯示圖片的任務(wù),Dispatcher 負(fù)責(zé)分發(fā)和處理,通過MemoryCache及Handler獲取圖片,通過PicassoDrawable顯示到Target中。

Picasso的優(yōu)點(diǎn):

•自帶統(tǒng)計(jì)監(jiān)控功能,支持圖片緩存使用的監(jiān)控,包括緩存命中率、已使用內(nèi)存大小、節(jié)省的流量等。
•支持優(yōu)先級(jí)處理,每次任務(wù)調(diào)度前會(huì)選擇優(yōu)先級(jí)高的任務(wù),比如 App 頁(yè)面中 Banner 的優(yōu)先級(jí)高于 Icon 時(shí)就很適用。
•支持延遲到圖片尺寸計(jì)算完成加載,支持飛行模式、并發(fā)線程數(shù)根據(jù)網(wǎng)絡(luò)類型而變,手機(jī)切換到飛行模式或網(wǎng)絡(luò)類型變換時(shí)會(huì)自動(dòng)調(diào)整線程池最大并發(fā)數(shù),比如 wifi 最大并發(fā)為 4, 4g 為 3,3g 為 2。這里 Picasso 根據(jù)網(wǎng)絡(luò)類型來決定最大并發(fā)數(shù),而不是 CPU 核數(shù)。

•“無”本地緩存,不是說沒有本地緩存,而是 Picasso 自己沒有實(shí)現(xiàn),交給了 Square 的另外一個(gè)網(wǎng)絡(luò)庫(kù) okhttp 去實(shí)現(xiàn),這樣的好處是可以通過請(qǐng)求 Response Header 中的 Cache-Control 及 Expired 控制圖片的過期時(shí)間。

Glide的設(shè)計(jì)及優(yōu)點(diǎn)

Glide的加載流程如下圖:


Glide 收到加載及顯示資源的任務(wù),Engine 處理請(qǐng)求,通過Fetcher獲取數(shù)據(jù),經(jīng)Transformation 處理后交給Target顯示。

Glide的優(yōu)點(diǎn):

(1) 圖片緩存->媒體緩存
Glide 不僅是一個(gè)圖片緩存,它支持 Gif、WebP、縮略圖。甚至是 Video,所以更該當(dāng)做一個(gè)媒體緩存。

(2) 支持優(yōu)先級(jí)處理

(3) 與 Activity/Fragment 生命周期一致,支持 trimMemory
Glide 對(duì)每個(gè) context 都保持一個(gè) RequestManager,通過 FragmentTransaction 保持與 Activity/Fragment 生命周期一致,并且有對(duì)應(yīng)的 trimMemory 接口實(shí)現(xiàn)可供調(diào)用。

(4) 支持 okhttp、Volley
Glide 默認(rèn)通過 UrlConnection 獲取數(shù)據(jù),可以配合 okhttp 或是 Volley 使用。實(shí)際 ImageLoader、Picasso 也都支持 okhttp、Volley。

(5) 內(nèi)存友好
① Glide 的內(nèi)存緩存有個(gè) active 的設(shè)計(jì)
從內(nèi)存緩存中取數(shù)據(jù)時(shí),不像一般的實(shí)現(xiàn)用 get,而是用 remove,再將這個(gè)緩存數(shù)據(jù)放到一個(gè) value 為軟引用的 activeResources map 中,并計(jì)數(shù)引用數(shù),在圖片加載完成后進(jìn)行判斷,如果引用計(jì)數(shù)為空則回收掉。

② 內(nèi)存緩存更小圖片
Glide 以 url、viewwidth、viewheight、屏幕的分辨率等做為聯(lián)合 key,將處理后的圖片緩存在內(nèi)存緩存中,而不是原始圖片以節(jié)省大小

③ 與 Activity/Fragment 生命周期一致,支持 trimMemory

④ 圖片默認(rèn)使用默認(rèn) RGB565 而不是 ARGB888
雖然清晰度差些,但圖片更小,也可配置到 ARGB_888。

其他:Glide 可以通過 signature 或不使用本地緩存支持 url 過期

關(guān)于Fresco

Fresco庫(kù)開源較晚,目前還沒有正式的1.0版本。但其功能比前三個(gè)庫(kù)都強(qiáng)大,比如:

•圖片存儲(chǔ)系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory),并不分配Java堆內(nèi)存,因此圖片加載不會(huì)引起堆內(nèi)存抖動(dòng);
•JPEG圖像流加載(先顯示圖像輪廓,再慢慢加載清晰圖像);
•更加完善的圖像處理、顯示方式;
•JPEG圖像本地(native)變換尺寸,避免OOM;
•……

關(guān)于系統(tǒng)匿名共享內(nèi)存Ashmem,會(huì)在后續(xù)的一篇關(guān)于Android的內(nèi)存使用的文章中詳述,這里僅作簡(jiǎn)單介紹:

在Android系統(tǒng)里面,Ashmem這個(gè)區(qū)域的內(nèi)存并不屬于Java Heap,也不屬于Native Heap。當(dāng)Ashmem中的某個(gè)內(nèi)存空間像要被釋放時(shí)候,會(huì)通過系統(tǒng)調(diào)用unpin來告知。但實(shí)際上這塊內(nèi)存空間的數(shù)據(jù)并沒有被真正的擦除。如果Android系統(tǒng)發(fā)現(xiàn)內(nèi)存吃緊時(shí),就會(huì)把unpin的內(nèi)存空間利用起來去存儲(chǔ)所需的數(shù)據(jù)。而被unpin的內(nèi)存空間,是可以被重新pin的,如果此時(shí)的該內(nèi)存空間還沒有被其他人使用的話,就節(jié)省了重新往Ashmem重新寫入數(shù)據(jù)的過程了。所以,Ashmem這個(gè)工作原理是一種延遲釋放。

另外,學(xué)習(xí)Ashmem可以參考羅升陽(yáng)大師的博客:

1.Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡(jiǎn)要介紹和學(xué)習(xí)計(jì)劃
2.Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)驅(qū)動(dòng)程序源代碼分析
3.Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)在進(jìn)程間共享的原理分析

二、PhotoView、GestureImageView的原理及使用

需要使用上述第三方開源庫(kù)進(jìn)圖片加載的一個(gè)典型場(chǎng)景是點(diǎn)擊查看大圖。大圖支持手勢(shì)縮放、旋轉(zhuǎn)、平移等操作,ImageView的手勢(shì)縮放,有很多種方法,絕大多數(shù)開源自定義縮放都是修改了ondraw函數(shù)來實(shí)現(xiàn)的。但是ImageView本身有scaleType屬性,通過設(shè)置android:scaleType="matrix" 可以輕松實(shí)現(xiàn)縮放功能。縮放的優(yōu)點(diǎn)是實(shí)現(xiàn)起來簡(jiǎn)單,同時(shí)因?yàn)闆]有反復(fù)調(diào)用ondraw函數(shù),縮放過程中不會(huì)有閃爍現(xiàn)象。另外,需要注意的是,scaleType控制圖片的縮放方式,該圖片指的是資源而不是背景,換句話說,android:src="@drawable/ic_launcher",而非android:background="@drawable/ic_launcher"。

在github上可以找到很多開源的實(shí)現(xiàn),這里主要舉兩個(gè)例子進(jìn)行簡(jiǎn)單說明。

PhotoView地址:https://github.com/bm-x/PhotoView.git

GestureImageView地址:https://github.com/jasonpolites/gesture-imageview.git

PhotoView的介紹:

1.Gradle添加依賴(推薦)

dependencies {
compile 'com.bm.photoview:library:1.3.6'
} 

(或者也可以將項(xiàng)目下載下來,將Info.java和PhotoView.java兩個(gè)文件拷貝到你的項(xiàng)目中,不推薦)——這種方式適用于Eclipse。

2.xml添加

<com.bm.library.PhotoView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:src="@drawable/bitmap1" /> 

3.java代碼

PhotoView photoView = (PhotoView) findViewById(R.id.img);
// 啟用圖片縮放功能
photoView.enable();
// 禁用圖片縮放功能 (默認(rèn)為禁用,會(huì)跟普通的ImageView一樣,縮放功能需手動(dòng)調(diào)用enable()啟用)
photoView.disenable();
// 獲取圖片信息
Info info = photoView.getInfo();
// 從一張圖片信息變化到現(xiàn)在的圖片,用于圖片點(diǎn)擊后放大瀏覽,具體使用可以參照demo的使用
photoView.animaFrom(info);
// 從現(xiàn)在的圖片變化到所給定的圖片信息,用于圖片放大后點(diǎn)擊縮小到原來的位置,具體使用可以參照demo的使用
photoView.animaTo(info,new Runnable() {
@Override
public void run() {
//動(dòng)畫完成監(jiān)聽
}
});
// 獲取動(dòng)畫持續(xù)時(shí)間
int d = PhotoView.getDefaultAnimaDuring(); 
PhotoView實(shí)現(xiàn)的基本原理是在繼承于ImageView的PhotoView中采用了縮放Matrix及手勢(shì)監(jiān)聽。
public class PhotoView extends ImageView {
……
private Matrix mBaseMatrix = new Matrix();
private Matrix mAnimaMatrix = new Matrix();
private Matrix mSynthesisMatrix = new Matrix();
private Matrix mTmpMatrix = new Matrix();
private RotateGestureDetector mRotateDetector;
private GestureDetector mDetector;
private ScaleGestureDetector mScaleDetector;
private OnClickListener mClickListener;
private ScaleType mScaleType;
……
} 

PhotoView的實(shí)現(xiàn)與上述原理基本一致,這里不再贅述。對(duì)于自定義控件的實(shí)現(xiàn),后續(xù)文章會(huì)進(jìn)行詳細(xì)的分析。

GestureImageView的簡(jiǎn)介如下:

1.Configured as View in layout.xml

code:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:gesture-image="http://schemas.polites.com/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.polites.android.GestureImageView
android:id="@+id/image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/image"
gesture-image:min-scale="0.1"
gesture-image:max-scale="10.0"
gesture-image:strict="false"/>
</LinearLayout> 

2.Configured Programmatically

code:

import com.polites.android.GestureImageView;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.LinearLayout.LayoutParams;
public class SampleActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
GestureImageView view = new GestureImageView(this);
view.setImageResource(R.drawable.image);
view.setLayoutParams(params);
ViewGroup layout = (ViewGroup) findViewById(R.id.layout);
layout.addView(view);
}
}

原理基本同PhotoView一致,不再贅述。

三、OOM分析工具——LeakCanary

LeakCanary的介紹:

A memory leak detection library for Android and Java.

可見,LeakCanary主要用于檢測(cè)各種內(nèi)存不能被GC,從而導(dǎo)致泄露的情況。

LeakCanary的地址 https://github.com/square/leakcanary.git

Demo地址:

https://github.com/liaohuqiu/leakcanary-demo.git(AS)

https://github.com/teffy/LeakcanarySample-Eclipse.git(Eclipse)

下面是demo中TestActivity中的TextView被靜態(tài)變量引用導(dǎo)致無法回收引起的內(nèi)存泄露的截圖。

LeakCanary的使用較為簡(jiǎn)單,首先添加依賴工程:

dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
} 

其次,在application的onCreate()方法中進(jìn)行初始化。

public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
} 

經(jīng)過這兩步之后就可以使用了。LeakCanary.install(this)會(huì)返回一個(gè)預(yù)定義的 RefWatcher,同時(shí)也會(huì)啟用一個(gè)ActivityRefWatcher,用于自動(dòng)監(jiān)控調(diào)用 Activity.onDestroy() 之后泄露的 activity。如果需要監(jiān)聽fragment,則在fragment的onDestroy()方法進(jìn)行注冊(cè):

public abstract class BaseFragment extends Fragment {
@Override public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(this);
}
} 

當(dāng)然,需要對(duì)某個(gè)變量進(jìn)行監(jiān)聽,直接對(duì)其進(jìn)行watch即可。

RefWatcher refWatcher = {...};
// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat); 

需要注意的是,在eclipse中使用LeakCanary需要在AndroidManifest文件中對(duì)堆占用分析以及展示的Service進(jìn)行申明:

<service
android:name="com.squareup.leakcanary.internal.HeapAnalyzerService"
android:enabled="false"
android:process=":leakcanary" />
<service
android:name="com.squareup.leakcanary.DisplayLeakService"
android:enabled="false" />
<activity
android:name="com.squareup.leakcanary.internal.DisplayLeakActivity"
android:enabled="false"
android:icon="@drawable/leak_canary_icon"
android:label="@string/leak_canary_display_activity_label"
android:taskAffinity="com.squareup.leakcanary"
android:theme="@style/leak_canary_LeakCanary.Base" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> 

注意:HeapAnalyzerService采用了多進(jìn)程android:process=":leakcanary"。

上述開源工具的使用都較為簡(jiǎn)單,關(guān)于詳細(xì)使用,請(qǐng)參考其github地址。

四、一些雜亂的總結(jié)

內(nèi)存泄露的常見原因:

•靜態(tài)對(duì)象:監(jiān)聽器,廣播,webview;
•this$0:線程,定時(shí)器,Handler;
•系統(tǒng):TextLine,輸入法,音頻

兜底回收內(nèi)存:

Activity泄露會(huì)導(dǎo)致該Activity引用的Bitmap/DrawingCache等無法釋放,兜底回收是指對(duì)已泄露的Activity,嘗試回收其持有的資源。在onDestroy中從rootview開始,遞歸釋放所有子VIew涉及的圖片,背景,DrawingCache,監(jiān)聽器等資源。

降低Runtime內(nèi)存的方法:

1.減少bitmap占用的內(nèi)存:1)防止bitmap占用資源過大,2.x系統(tǒng)打開BitmapFactory.Options中的inNativeAlloc;4.x系統(tǒng)采用Facebook的fresco庫(kù),將圖片資源放于native中。2)圖片按需加載,圖片的大小不應(yīng)超過view的大小。3)統(tǒng)一的bitmap加載器:Picasso/Fresco。4)圖片存在像素浪費(fèi)。

2.自身內(nèi)存占用監(jiān)控:1)實(shí)現(xiàn)原理:通過Runtime獲取maxMemory,而totalMemory-freeMemory即為當(dāng)前真正使用的dalvik內(nèi)存。2)操作方式:定期檢查這個(gè)值,達(dá)到80%就去釋放各種cache資源(bitmap的cache)

3.使用多進(jìn)程。對(duì)于webview,圖庫(kù)等,由于存在內(nèi)存系統(tǒng)泄露,可以采用單獨(dú)的進(jìn)程。

相關(guān)文章

  • 一文搞懂Android RecyclerView點(diǎn)擊展開、折疊效果的實(shí)現(xiàn)代碼

    一文搞懂Android RecyclerView點(diǎn)擊展開、折疊效果的實(shí)現(xiàn)代碼

    雖然在日常開發(fā)中已經(jīng)多次接觸過RecycleView,但也只是用到其最基本的功能,并沒有深入研究其他內(nèi)容。接下來將抽出時(shí)間去了解RecycleView的相關(guān)內(nèi)容,這篇文章主要是介紹Android RecyclerView點(diǎn)擊展開、折疊效果的實(shí)現(xiàn)方式,一起看看吧
    2021-06-06
  • Android React Native原生模塊與JS模塊通信的方法總結(jié)

    Android React Native原生模塊與JS模塊通信的方法總結(jié)

    這篇文章主要介紹了Android React Native原生模塊與JS模塊通信的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • android客戶端從服務(wù)器端獲取json數(shù)據(jù)并解析的實(shí)現(xiàn)代碼

    android客戶端從服務(wù)器端獲取json數(shù)據(jù)并解析的實(shí)現(xiàn)代碼

    今天總結(jié)一下android客戶端從服務(wù)器端獲取json數(shù)據(jù)的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2013-06-06
  • Android端部署DeepSeek的詳細(xì)教程

    Android端部署DeepSeek的詳細(xì)教程

    DeepSeek最近幾個(gè)月很火熱,很多產(chǎn)品以及企業(yè)都在接入DeepSeek,比如微信搜索接入,可以搜索公眾號(hào)信息并總結(jié),這個(gè)對(duì)于查一些資料還挺好用,畢竟手機(jī)才是用戶用的最多的,既然談到了手機(jī),那么DeepSeek能否部署于手機(jī)之上呢,本文給大家介紹了android端部署的DeepSeek方法
    2025-03-03
  • Android  SharedPreferences四種操作模式使用詳解

    Android SharedPreferences四種操作模式使用詳解

    這篇文章主要介紹了Android SharedPreferences四種操作模式使用詳解的相關(guān)資料,這里介紹了獲取Android SharedPreferences的兩種方法及比較,和操作模式的介紹,需要的朋友可以參考下
    2017-07-07
  • Android 系統(tǒng)簽名 keytool-importkeypair的操作步驟

    Android 系統(tǒng)簽名 keytool-importkeypair的操作步驟

    本文介紹了在Android項(xiàng)目中使用系統(tǒng)簽名并打包APK的方法,步驟包括獲取系統(tǒng)簽名文件、修改AndroidManifest.xml、轉(zhuǎn)換簽名文件、配置Android Studio簽名、生成APK文件和打包APK,感興趣的朋友一起看看吧
    2025-01-01
  • 如何利用Kotlin實(shí)現(xiàn)極簡(jiǎn)回調(diào)

    如何利用Kotlin實(shí)現(xiàn)極簡(jiǎn)回調(diào)

    這篇文章主要給大家介紹了關(guān)于如何利用Kotlin實(shí)現(xiàn)極簡(jiǎn)回調(diào)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • Flutter使用sqflite處理數(shù)據(jù)表變更的方法詳解

    Flutter使用sqflite處理數(shù)據(jù)表變更的方法詳解

    了解過數(shù)據(jù)庫(kù)的同學(xué)應(yīng)該會(huì)知道,數(shù)據(jù)表結(jié)構(gòu)是可能發(fā)生改變的。所以本文為大家介紹了Flutter?使用?sqflite?處理數(shù)據(jù)表變更的版本升級(jí)處理方法,感興趣的可以了解一下
    2023-04-04
  • Android自定義View圓形和拖動(dòng)圓、跟隨手指拖動(dòng)效果

    Android自定義View圓形和拖動(dòng)圓、跟隨手指拖動(dòng)效果

    單純的自定義一個(gè)圓非常簡(jiǎn)單 只需要幾步就完成 拖動(dòng)圓添加實(shí)現(xiàn)觸摸事件即可 。接下來通過本文給大家分享Android自定義View圓形和拖動(dòng)圓、跟隨手指拖動(dòng)效果,感興趣的朋友一起看看吧
    2017-09-09
  • Kotlin圖文并茂講解續(xù)體與續(xù)體攔截器和調(diào)度器

    Kotlin圖文并茂講解續(xù)體與續(xù)體攔截器和調(diào)度器

    這篇文章主要介紹了Kotlin開發(fā)中續(xù)體與續(xù)體攔截器和調(diào)度器的相關(guān)使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08

最新評(píng)論

彝良县| 荣昌县| 清流县| 钟祥市| 凤冈县| 金塔县| 子长县| 钟祥市| 八宿县| 石门县| 盱眙县| 高平市| 桐梓县| 巩义市| 乌海市| 镇雄县| 高清| 保亭| 绩溪县| 阳泉市| 井陉县| 兴山县| 凤冈县| 漳州市| 通道| 玉田县| 彰化市| 达拉特旗| 濮阳县| 通江县| 鸡泽县| 海南省| 深泽县| 柳江县| 利津县| 武强县| 富顺县| 柯坪县| 汝南县| 闻喜县| 会昌县|