Android開發(fā)常見問題總結(jié)(持續(xù)更新)

滑動

  1. 滑動嵌套

滑動組件的嵌套可能會產(chǎn)生以下一些問題:

  • 滑動沖突

解決方法:使用NestedScrollView替代ScrollView誊垢,RecyclerView可以設(shè)置屬性android:nestedScrollingEnabled="false"或代碼里setNestedScrollingEnabled(false);來禁用組件自身的滑動

注意:如果RecyclerView只能顯示一個Item的話酵紫,需要設(shè)置NestedScrollView的屬性android:fillViewport="true"

  • 滑動失效

ScrollView設(shè)置fillViewport="true"的情況下席楚,如果對ScrollView的直接子view設(shè)置上下margin醇疼,在超出內(nèi)容的高度小于設(shè)置的margin的情況下,可能會導(dǎo)致整個ScrollView滑動失效

  1. 焦點(diǎn)搶占

ScrollView听想、RecyclerView等滑動組件可能會搶占焦點(diǎn)眼虱,導(dǎo)致界面顯示時直接滑動到對應(yīng)組件的位置,而不是頂部

解決方法:在頂部View(或者其他你所期望的初始位置)加上屬性android:focusable="true"android:focusableInTouchMode="true"

新解決方法:在頂部View上加android:descendantFocusability屬性僵朗,該屬性是用來定義父布局與子布局之間的關(guān)系的赖欣,它有三種值:

  • beforeDescendants:父布局會優(yōu)先其子類控件而獲取到焦點(diǎn)
  • afterDescendants:父布局只有當(dāng)其子類控件不需要獲取焦點(diǎn)時才獲取焦點(diǎn)
  • blocksDescendants:父布局會覆蓋子類控件而直接獲得焦點(diǎn)

使用blocksDescendants覆蓋子布局焦點(diǎn)以解決焦點(diǎn)搶占問題


RecyclerView

Adapter

  1. onBindViewHolder中設(shè)置子View回調(diào)時需要注意

如果回調(diào)的參數(shù)包括position時歌径,需要注意有沒有地方會調(diào)用notifyItemRemovednotifyItemRangeRemoved戈毒,如果有,需要使用holder.getAdapterPosition()來代替onBindViewHolder方法的position參數(shù)

原因:notifyItemRemoved不會對其他的Item重新調(diào)用onBindViewHolder甥厦,這樣可能會導(dǎo)致position錯位粪薛。holder.getAdapterPosition()方法會返回數(shù)據(jù)在 Adapter 中的位置(即使位置的變化還未刷新到布局中)

  1. 如何在更新數(shù)據(jù)后重新定位到頂部
//重寫父類方法云矫,獲得綁定的RecyclerView
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
    mRecyclerView = recyclerView;
}

//當(dāng)數(shù)據(jù)更新后調(diào)用
if (mRecyclerView != null && mRecyclerView.getChildCount() > 0) {
    mRecyclerView.scrollToPosition(0);
}

之前嘗試過mRecyclerView.scrollTo(0, 0);但沒有起效,不清楚為什么

  1. 動態(tài)部分更新數(shù)據(jù)時

如果RecyclerView需要動態(tài)更新部分數(shù)據(jù),并且在onBindViewHolder時對某些view設(shè)置了事件或者回調(diào)等让禀,如果此時使用到了position參數(shù)需要注意挑社,如果你只notify了部分?jǐn)?shù)據(jù)更新,可能會導(dǎo)致更新后部分ViewHolder中的回調(diào)里的position不正確巡揍,建議:

  • 使用notifyDataSetChanged()
  • 使用notifyItem痛阻,但是在onBindViewHolder中設(shè)置回調(diào)時不要使用position參數(shù),而是使用holder.getAdapterPosition()替代(注意這個方法在ViewHolder沒有和RecyclerView綁定時會返回-1 NO_POSITION

Dialog

  1. 生命周期
  • 初始化時需要注意

Dialog在第一次調(diào)用show()方法后才會執(zhí)行onCreate(Bundle savedInstanceState)方法腮敌,因此建議自定義Dialog時將findViewById等初始化操作放在構(gòu)造函數(shù)中進(jìn)行阱当,避免外部使用時因在show()之前設(shè)置視圖數(shù)據(jù)導(dǎo)致NPE


PopupWindow

  1. 點(diǎn)擊沒反應(yīng)

PopupWindow如果不設(shè)置背景的話,在某些5.x以下系統(tǒng)機(jī)型上會出現(xiàn)點(diǎn)擊沒反應(yīng)的問題

解決方法:給PopupWindow設(shè)置一個空背景popupWindow.setBackgroundDrawable(new BitmapDrawable(mContext.getResources(), (Bitmap) null));

詳見:juejin.cn/post/684490…


廣播

  1. 隱式廣播

在Android8.0以上的系統(tǒng)糜工,大部分的隱式廣播都被限制不可使用弊添。

解決方法:

  1. 使用動態(tài)廣播
  2. 使用顯示廣播
// 方式一: 設(shè)置Component
Intent intent = new Intent(SOME_ACTION);
intent.setComponent(new ComponentName(context, SomeReceiver.class));
context.sendBroadcast(intent);

// 方式二: 設(shè)置Package
Intent intent = new Intent(SOME_ACTION);
intent.setPackage("com.dreamgyf.xxx");
context.sendBroadcast(intent);

// 不知道包名的話可以通過PackageManager獲取所有注冊了指定action的廣播的package
Intent actionIntent = new Intent(SOME_ACTION);
PackageManager pm = context.getPackageManager();
List<ResolveInfo> matches = pm.queryBroadcastReceivers(actionIntent, 0);
for (ResolveInfo resolveInfo : matches) {            
    Intent intent = new Intent(actionIntent);            
    intent.setPackage(resolveInfo.activityInfo.applicationInfo.packageName);            
    intent.setAction(SOME_ACTION);            
    context.sendBroadcast(intent);        
}


實(shí)體鍵盤

  1. EditText有焦點(diǎn)時會攔截鍵盤的數(shù)字鍵

解決方法:使用TextWatcher等監(jiān)聽EditText輸入


內(nèi)存泄漏

  1. 動畫

在Activity銷毀之前如果沒有cancel掉,會導(dǎo)致這個Activity內(nèi)存泄漏

  1. ClickableSpan

使用SpannableString.setSpan方法設(shè)置ClickableSpan可能導(dǎo)致內(nèi)存泄漏

原因:TextViewonSaveInstanceState時會將ClickableSpan復(fù)制一份捌木,由于某些原因油坝,SpannableString不會刪除這個ClickableSpan,從而導(dǎo)致內(nèi)存泄漏刨裆,詳見: StackOverflow

解決方法:自定義一個抽象類同時繼承ClickableSpan和實(shí)現(xiàn)NoCopySpan接口澈圈,外部setSpan時使用這個抽象類


Fragment

  1. Fragment盡量不要使用帶參構(gòu)造函數(shù),一定要保證有一個不含參的構(gòu)造函數(shù)帆啃,否則在Activity重建時嘗試反射newInstance恢復(fù)Fragment時會拋出Could not find Fragment constructor異常

混淆

  1. 反射

如果使用到了反射瞬女,需要特別注意需不需要在proguard-rules中加入keep規(guī)則

  1. module混淆

如果是多module項(xiàng)目,想要在module中增加混淆規(guī)則努潘,proguardFiles屬性是無效的诽偷,應(yīng)該使用consumerProguardFiles屬性

android {
    compileSdkVersion 28

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 28
        versionName repo.version

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        consumerProguardFiles 'proguard-rules.pro' //這里
    }
    ...
}


相機(jī)開發(fā)

  1. 拍照角度

相機(jī)的方向一般是以手機(jī)橫向作為正方向,這樣如果我們以豎屏的方式拍照疯坤,拍出來的照片可能會出現(xiàn)旋轉(zhuǎn)了90度的情況报慕,這時候就需要在拍照完后處理一下圖片,旋轉(zhuǎn)到正確位置贴膘。

具體介紹與算法在Android SDK中CaptureRequest.JPEG_ORIENTATION的注釋中

private int getJpegOrientation(CameraCharacteristics c, int deviceOrientation) {
    if (deviceOrientation == android.view.OrientationEventListener.ORIENTATION_UNKNOWN)
        return 0;
    //獲得相機(jī)方向與設(shè)備方向間的夾角
    int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);

    // Round device orientation to a multiple of 90
    deviceOrientation = (deviceOrientation + 45) / 90 * 90;

    // Reverse device orientation for front-facing cameras
    boolean facingFront = c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
    if (facingFront) deviceOrientation = -deviceOrientation;

    // Calculate desired JPEG orientation relative to camera orientation to make
    // the image upright relative to the device orientation
    int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360;

    return jpegOrientation;
}

計算好角度后就可以對圖片做旋轉(zhuǎn)了,網(wǎng)上有很多文章都說使用這種方式做旋轉(zhuǎn)

captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getJpegOrientation(deviceRotation));

但實(shí)際上在某些系統(tǒng)上 (MIUI)略号,設(shè)置的這個參數(shù)并不會生效刑峡,所以我的方案是,獲得拍攝好的照片Bitmap后玄柠,再對其進(jìn)行旋轉(zhuǎn)

public Bitmap rotateBitmap(Bitmap bitmap, int angle) {
   Matrix matrix = new Matrix();
   matrix.setRotate(angle);
   return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}

相關(guān)推薦

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末突梦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子羽利,更是在濱河造成了極大的恐慌宫患,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件这弧,死亡現(xiàn)場離奇詭異娃闲,居然都是意外死亡虚汛,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門皇帮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來卷哩,“玉大人,你說我怎么就攤上這事属拾〗辏” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵渐白,是天一觀的道長尊浓。 經(jīng)常有香客問我,道長纯衍,這世上最難降的妖魔是什么栋齿? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮托酸,結(jié)果婚禮上褒颈,老公的妹妹穿的比我還像新娘。我一直安慰自己励堡,他們只是感情好谷丸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著应结,像睡著了一般刨疼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鹅龄,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天揩慕,我揣著相機(jī)與錄音,去河邊找鬼扮休。 笑死迎卤,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的玷坠。 我是一名探鬼主播蜗搔,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼八堡!你這毒婦竟也來了樟凄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤兄渺,失蹤者是張志新(化名)和其女友劉穎缝龄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叔壤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年瞎饲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片百新。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡企软,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饭望,到底是詐尸還是另有隱情仗哨,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布铅辞,位于F島的核電站厌漂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏斟珊。R本人自食惡果不足惜苇倡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望囤踩。 院中可真熱鬧旨椒,春花似錦、人聲如沸堵漱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勤庐。三九已至示惊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愉镰,已是汗流浹背米罚。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丈探,地道東北人录择。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像碗降,于是被迫代替她去往敵國和親隘竭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

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