一些知识点的整理以及面试题记录
每日任務
2018年3月2日
-Service-和-IntentService-的區別
鏈接
Service
Service是長期運行在后臺的應用程序組件。 Service不是一個單獨的進程,它和應用程序在同一個進程中,Service也不算是一個線程,它和線程沒有任何關系,所有它不能直接處理耗時操作。如果直接把耗時操作放在Service的onStartCommand()中,很容易引起ANR,如果有耗時操作就必須開啟一個單獨的線程來處理。 復制代碼IntentService
IntentService是繼承于Service并處理異步請求的一個類,在IntentService內有一個工作線程來處理耗時操作,啟動IntentService的方式和啟動傳統Service一樣,同時,當任務執行完后,IntentService會自動停止,而不需要我們去手動控制。另外,可以啟動IntentService多次,而每一個耗時操作都會以工作隊列的方式在IntentService的onHandlerIntent回調方法中執行,并且,每次只會執行一個工作線程,執行完第一個再執行第二個,以此類推。 復制代碼2018年3月3日
閱讀記錄
- 閱讀:機器學習速成課程-降低損失 (Reducing Loss)
- 閱讀:精通比特幣-1.4入門:
復習點
- 閱讀:精通比特幣-HD協議:
- 閱讀:JVM——Java虛擬機架構 :heavy_check_mark:
- 閱讀:Kotlin Primer·第二章·基本語法
- 閱讀:Android面試一天一題(1 Day):heavy_check_mark:
- 閱讀:Android studio代碼格式規范
- 閱讀:Android進階筆記09:Android開發經驗部分總結:heavy_check_mark:
- 閱讀:借騰訊開源 VasDolly,談談 Android 簽名和多渠道打包的原理!
- 閱讀:收集了50道基礎的java面試題
- 閱讀:Android開源框架源碼鑒賞:VirtualAPK
-堆和棧的區別
在這里輸入圖片標題堆和棧的區別
重要復習點
1.png2.png3.png4.png待閱讀
視頻:Android-屏幕適配全攻略
2018年3月5日
重要復習點
- Android內存泄漏--imageloader???
- android解決加載大圖片卡頓和oom問題。
尺寸壓縮之inSampleSize 為了防止加載圖片時內存溢出,需要先計算采樣率,然后再去加載圖片。
-
算法一:圖片長與目標長比,圖片寬與目標寬比,取最大值。
-
算法二:取目標長寬的最大值來計算,這樣會減少過度的尺寸壓縮。
2018年3月6日
Android-壓縮大圖到容量超小的圖片
原文
壓縮圖片的寬高
/*** 計算圖片的壓縮比** @param options* @param reqWidth* @param reqHeight* @return*/public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {final int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;//壓縮比if (height > reqHeight || width > reqWidth) {final int halfHeight = height / 2;final int halfWidth = width / 2;while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {inSampleSize*=2;}}return inSampleSize;} 復制代碼調用calculateInSampleSize計算壓縮比。并解碼原圖為Bitmap:
/*** @param imagePath* @param displayWidth* @param displayHeight* @return*/private Bitmap compress(String imagePath, int displayWidth, int displayHeight) {BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;//只測量image 不加載到內存。BitmapFactory.decodeFile(imagePath, options);//測量imageoptions.inPreferredConfig = Bitmap.Config.RGB_565;//設置565編碼格式,省內存,options.inSampleSize = calculateInSampleSize(options, displayWidth, displayHeight);options.inJustDecodeBounds = false;Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);//按照Options配置去加載圖片到內存return bitmap;} 復制代碼這里比較重要的inJustDecodeBounds字段,當inJustDecodeBounds為true時,調用BitmapFactory.decode時并沒有把圖片加載到內存中去,只是去測量圖片的寬高,不不占用內存,當inSampleSize為false時,調用BitmapFactory.decoe時就把圖片加載到內存去了,所有獲取bitmap應在inJustDecodeBounds為false后的BitmapFactory.decode去獲取。
設置編碼格式 android中默認格式是ARG8888,我們解碼圖片一般用ARG565節省圖片加載到內存的大小。
ALPHA_8 代表8位Alpha位圖 ARGB_4444 代表16位ARGB位圖 ARGB_8888 代表32位ARGB位圖 RGB_565 代表8位RGB位圖 復制代碼位圖位數越高代表其可以存儲的顏色信息越多,當然圖像也就越逼真
圖片質量壓縮
ByteArrayOutputStream out = new ByteArrayOutputStream();//字節流輸出 bitmap.compress(Bitmap.CompressFormat.JPEG,50,out);//壓縮成jpeg格式復制代碼compress中第一個參數是輸出文件的格式,在Bitmap枚舉類CompressFormat中定義,有JPEG,PNG PNG,WEBP,一般選擇JPEG,壓縮出來的容量小,WEBP很耗時, 耗時時間比較:WEBP>PNG>JPEG, 壓縮大小:PNG>WEBP>JPEG. 第二個參數是壓縮的質量比例,也就是壓縮像素的顯示色彩,當100時表示不壓縮。當為50時表示壓縮50%的質量。設置這個參數可以有效的極大的縮小圖片的大小,可以按照自己的需求進行設置, 但建議一般不要大于60.第三個參數就是想要寫入的圖片數據的字節流數組了。
字節流寫出文件
我們經過上述步驟后,就拿到了字節流數據了,此時我們可以根據項目需求直接上傳字節流或者保存為本地圖片再上傳。
ByteArrayOutputStream out = new ByteArrayOutputStream();//字節流輸出bitmap.compress(Bitmap.CompressFormat.JPEG, 50, out);//壓縮成jpeg格式 壓縮像素質量為50%String fileName = imagePath.substring(imagePath.lastIndexOf("/") + 1, imagePath.lastIndexOf("."));//獲取文件名File outFile = new File("/storage/emulated/0/photoPickTemp", fileName + "_temp.jpeg");//創建壓縮后的image文件try {if (!outFile.exists()) {//判斷文件是否存在if (outFile.createNewFile()) {//判斷創建新文件是否成功FileOutputStream fos = new FileOutputStream(outFile);byte[] bytes = out.toByteArray();//字節數組int count = bytes.length;fos.write(bytes, 0, count);fos.close();//關閉流out.close();}}} catch (Exception e) {e.printStackTrace();} 復制代碼獲取當前屏幕寬高
工具類
封裝
public class ImageUtil {public ImageUtil(){}public static File compressImage(String imagePath,int displayWidth,int displayHeight){BitmapFactory.Options options=new BitmapFactory.Options();options.inJustDecodeBounds=true;//只測量image 不加載到內存BitmapFactory.decodeFile(imagePath,options);//測量imageoptions.inPreferredConfig= Bitmap.Config.RGB_565;//設置565編碼格式 省內存options.inSampleSize=calculateInSampleSize(options,displayWidth,displayHeight);//獲取壓縮比 根據當前屏幕寬高去壓縮圖片options.inJustDecodeBounds=false;Bitmap bitmap=BitmapFactory.decodeFile(imagePath,options);//按照Options配置去加載圖片到內存ByteArrayOutputStream out=new ByteArrayOutputStream();//字節流輸出bitmap.compress(Bitmap.CompressFormat.JPEG,50,out);//壓縮成JPEG格式 壓縮像素質量為50%String fileName=imagePath.substring(imagePath.lastIndexOf("/")+1,imagePath.lastIndexOf("."));//獲取文件名稱File outFile=new File("/storage/emulated/0/PhotoPickTemp",fileName+"_temp.jpeg");//創建壓縮后的image文件try {if(!outFile.exists()){//判斷新文件是否存在if(outFile.createNewFile()){//判斷創建新文件是否成功FileOutputStream fos=new FileOutputStream(outFile);//創建一個文件輸出流byte[] bytes=out.toByteArray();//字節數組int count=bytes.length;//字節數組的長度fos.write(bytes,0,count);//寫到文件中fos.close();//關閉流out.close();}}} catch (IOException e) {e.printStackTrace();}return outFile;}public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){//計算圖片的壓縮比final int height=options.outHeight;//圖片的高度final int width=options.outWidth;//圖片的寬度 單位1px 即像素點int inSampleSize=1;//壓縮比if(height>reqHeight||width>reqWidth){final int halfHeight=height/2;final int halfWidth=width/2;while ((halfHeight/inSampleSize)>=reqHeight&&(halfWidth/inSampleSize)>=reqWidth){inSampleSize*=2;}}return inSampleSize;} } 復制代碼Android-性能優化
布局優化
- 布局嵌套過深
- 使用合適的布局
- 列表控件優化
- 使用include標簽
- ViewStub延時加載
- 移除Activity默認背景
線程優化
ViewPager,ScrollView-嵌套ViewPager滑動沖突解決
原文
Android事件分發機制
圖解 Android 事件分發機制
- 對于dispathTouchEvent,onTouchEvent,return true 是終結事件傳遞。return false 是回溯到父View的onTouchEvent方法。
- ViewGroup想把自己分發給自己的onTouchEvent,需要攔截器onInterecptTouchEvent方法return true把事件攔截下來。
- ViewGroup的攔截器默認是不攔截的。所以super.onInterecptTouchEvent()= return true;
- View沒有攔截器,為了讓View可以把事件分發給自己的onTouchEvent,View的dispatchTouchEvent默認實現(super)就是把事件分發給自己的onTouchEvent
ViewGroup和View的dispatchTouchEvent是做事件分發,那么這個事件分發可能分發出去的四個目標。
java鎖的種類以及辨析
自旋鎖
采用讓當前線程不停地在循環體內執行實現的。當循環條件被其他線程改變時,才進入臨界區
阻塞鎖(synchronized)
可重入鎖(遞歸鎖)
指的是同一線程外層函數獲得鎖之后,內層遞歸函數仍然有獲取該鎖的代碼,但不受影響。 可重入鎖最大的作用是避免死鎖。
互斥鎖的優缺點: - 優點:能有效防止因多線程搶奪資源造成數據安全的問題 - 缺點:需要消耗大量的CPU資源。互斥鎖的使用前提:多條線程搶奪同一塊資源。** 自旋鎖更適合做一些較短的操作 ** 復制代碼ANR
ANR
應用程序無響應。
為什么會產生ANR
-
5s內無法響應用戶輸入事件(例如鍵盤輸入,觸摸屏幕等)
-
BroadcastReceiver在10s內無法結束
造成以上兩種情況的首要原因就是在主線程(UI線程)里面做了太多的阻塞耗時操作,例如:文件讀寫,數據庫讀寫,網絡查詢。
如何避免ANR
不要在主線程里面做繁重的操作
ANR的處理
開辟單獨的子線程來處理耗時阻塞事物。
I/O阻塞一般就是文件讀寫或者數據庫操作執行在主線程了,也可以通過開辟子線程的方式異步執行。
增大VM內存,使用largeHeap屬性,排查內存泄露
RxJava
給 Android 開發者的 RxJava 詳解-flatMap():
2018年3月8日
Android-安裝文件(APK)瘦身
2018年3月9日
Android應用程序啟動過程源代碼分析
Step 1. Launcher.startActivitySafely
在Android系統中,應用程序是由launch啟動起來的,其實,launch本身也是一個應用程序,其他的應用程序安裝后,就會launcher的界面上出現一個相應的圖標。點擊這個圖標,launcher就會對應的應用程序啟動起來。 復制代碼Android2017-2018最新面試題(3-5年經驗個人面試經歷)
面試題(固定答案不解答,自己可以找到)
大圖加載控件
大圖加載控件
2018年3月12日
Android插件化與熱修復
DynamicApk-攜程
- 支持類的加載
- 用代理的方式加載Activity
- 反射方式加載資源
沒有像DroidPlugin那樣是資源獨立的,而是采用同一套資源,用資源名稱去區分不同的資源,針對資源的id也做修改,Activity的加載方式是采用代理的方式讓系統識別的。
文章地址
github地址
DroidPlugin-360手機助手
原理:利用Android一個進程可以運行多個apk的機制,通過API欺騙讓系統認為只有宿主app存在,同時通過預先占坑來創造插件app的運行環境,最后通過動態代理實現函數hook,Binder代理繞過部分系統服務限制,從而實現應用的組件化。
- DroidPlugin這個是跟360安全的產品密切相關的,也非常適合360手機助手。 DroidPlugin的目標是使任何一個app都可以在DroidPlugin的宿主應用中直接運行。而不是將app安裝到手機中,再去體驗app。
- DroidPlugin中使用了大量的hook相關技術,特別是在Activity的注冊上,做了預先注冊一些Activity,然后在新的Activity啟動時欺騙系統是預先注冊過的Activity。 DroidPlugin最精華的就是hook技術。
GitHub地址
HotFix-QQ空間熱補丁技術
主要技術是:系統在安裝app的時候會在類加載器中加載apk中的默認classes.dex文件。這個類加載器可以加載后續的補丁Dex文件,而且可以調整Dex文件的加載順序,這樣就可以用同名的類去替換掉原始的含有bug的類,已達到修復bug的目的。
AndFix-阿里支付寶
- AndFix的原理是方法的替換,把有bug的方法替換成補丁文件中的方法,在Native層使用指針替換的方式替換bug的方法,已達到修復bug的目的。
Alibaba-AndFix Bug熱修復框架原理及源碼解析
Tinker-微信
在客戶端將補丁文件和app原始文件進行合并,用客戶端的存儲空間換取網絡傳輸的流量和app的運行效率。Tinker目前開源支持的比較好,網上資料相對多一些,在編譯時通過新舊兩個Dex文件生成差異的patch.dex文件,在app中將差異的patch.dex文件重新跟原始安裝包的原始的Dex文件生成新的Dex文件。這個過程會耗費app的運行時間和內存,所以Tinker將其單獨放在一個后臺進程:patch中。為了將補丁包盡量的小,Tinker自研了DexDiff算法,他深度利用Dex的格式來減少差異文件的大小。
2018年3月13日
Java基礎
java中==和equals和hashCode的區別
==
結果是:true,false,true
對象類型的比較,比較的是地址(引用),而非值本身,也是就是說他們實際存儲的內存地址不同。
equals
比較兩個對象的引用是否相等,即 是否指向同一個對象。
總結
對于==,如果作用于基本數據類型,則直接比較其存儲的“值”是否相等,如果作用于引用類型的變量,則比較的是所指向的對象的地址。
對于 equals 方法,注意:equals不能作用于基本數據類型,如果沒有對equals進行重寫,則比較的是 引用類所指向的地址。如果重寫了,比較的就是對象的內容。
hashCode
用來鑒定兩個對象是否相等,Object類中的hashCode方法返回對象在內存中地址轉換成的一個int值,所以如果沒有重寫hashCode方法,任何對象的hashCode方法是不相等的。
設計hashCode()時最重要的因素就是:無論何時,對同一個對象調用hashCode都應該產生同一個值。
如果重寫了equals方法就必須要重寫hashCode方法,以便用戶將對象插入到散列表中。
equals相等的兩個對象,hashCode一定相等,equals不相等的兩個對象,卻并不能證明他們的hashCode不相等。
equals方法不相等的兩個對象,hashCode有可能相等,
在每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法,如果不這樣做的話,就會違反Object.hashCode的通用約定。從而導致該類無法結合所有基于散列的集合一起正常運作。
int、char、long 各占多少字節數
-
byte 是 字節
-
bit 是 位
1 byte = 8 bit
- char在java中是2個字節,java采用unicode,2個字節來表示一個字符
- short 2個字節
- int 4個字節
- long 8個字節
- float 4個字節
- double 8個字節
int 與 integer 區別
記錄-
2.4 比特幣挖礦
2018 BAT等大廠最全面試題集錦
6.4.1 圖靈非完備性
2018年3月14日
String、StringBuffer、StringBuilder區別
- String :字符串常量(線程安全)
字符串是不變的,他們的值在創造后就不能改變。 字符串緩沖區支持可變字符串。因為字符串對象是不可變的,所以他們可以共享。
總結歸納了String的兩個最重要的特點:
-
StringBuilder:字符串變量(非線程安全)
-
StringBuffer:字符串變量(線程安全)
是一個容器,最終會通過toString方法變成字符串。
String與StringBuffer區別
- 主要區別:在修改時對象自身是否可變
String在修改時不會改變對象自身。每次對String類型進行改變的時候其實都等同于生成了一個新的String對象,然后將指針指向了新的String對象,所以經常改變內容的字符串最好不要用String。
StringBuffer在修改時會改變對象自身。每次結果都會對StringBuffer對象本身進行操作,而不是生成新的對象,改改變對象引用,所以一般情況下我們推薦使用StringBuffer,特別是字符串對象經常改變的情況下,StringBuffer的主要操作是append和insert方法
- StringBuffer對象和String對象之間的互轉:
總結
- 如果要操作少量的數據用String
- (多線程下)經常需要對一個字符串進行修改,例如追加、插入和刪除等操作,使用StringBuffer更加適合一些。
StringBuffer與StringBuilder區別
- StringBuilder是可變的對象,是5.0新增的 此類提供一個與StringBuffer兼容的API,但不保證同步,該類被設計用作StringBuffer的一個簡易替換,用在字符串緩沖區被單個線程使用的時候(這種情況很普遍)
- 線程安全性:
- String、StringBuilder、StringBuffer速度區別
- 特殊情況, String > StringBuffer
總結
對java多態的理解
- 什么是多態
- 多態的好處:
java中多態的實現方式:接口實現,繼承父類進行方法的重寫,同一個類中方法重載。
多態的三要素:1.繼承。2.重寫。3.父類引用指向子類對象
package objectandclass; class A { public void show(D obj){ System.out.println("A and D"); } public void show(A obj){ System.out.println ("A and A"); } } class B extends A{ public void show(B obj){ System.out.println("B and B"); } public void show(A obj){ System.out.println("B and A"); } } class C extends B{} class D extends B{} A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); a1.show(b); //A and Aa1.show(c); //A and Aa1.show(d); //A and Da2.show(b); //B and Aa2.show(c); //B and Aa2.show(d); //A and Db.show(b); //B and Bb.show(c); //B and Bb.show(d); //A and D 復制代碼2018年3月15日
什么是內部類?內部類的作用
定義
就是定義在另外一個類里面的類,與之對應,包含內部類的類被稱為外部類。
作用
2018年3月16日
抽象類和接口
- 抽象類:對一類事物的抽象
定義: 如果一個類中沒有包含足夠多的信息來描述一個具體的對象,這樣的類就是抽象類。
- 接口:對某一行為的抽象
定義: 接口在java中是一個抽象類型,是抽象方法的集合。一個類通過實現接口的方式,從而繼承接口中的抽象方法。
抽象類的意義:
區別總結:
抽象類是對事物的抽象,接口是對行為的抽象;抽象類是對整個類的抽象,包括行為,屬性;接口是對類的行為(局部)進行抽象。
設計抽象類是自下而上的過程,我子類需要,所以我定義抽象類;設計接口是自上而下的過程,我接口規范某一行為,我某類需要這個行為,我某類實現某接口。
核心區別:
調用者使用的動機不同,實現接口 為了使用其他規范的某一個行為;繼承抽象類是為了使用這個類的屬性和行為 復制代碼總結
使用場景
再設計類時,如果有些方法我們能確定,而有些方法不能確定,這時候就可以定義成抽象類。抽象類的應用場景非常多,例如模板方法模式就是抽象類的一個應用,JDK中inputStream和outputStream也是抽象類的一個應用,這兩個類定義了如何讀寫數據的方法,而沒有定義從哪里去讀,具體從哪里讀是由具體的實現子類確定。
我們在定義相互調用規則時,可以使用接口,面向接口進行編程的好處,就是能極大地降低軟件系統的耦合性,接口的定義按照接口進行調用,而實現者去實現接口。 在JDK中存在很多針對接口的編程,例如用于我們比較兩個對象的Comparable接口就是一個典型的案例,我們在自定義對象時,如果實現了該接口,那么我們把對象保存到treeset集合中,treeset將針對接口調用對象的compareTo方法。
2018年3月19日
加載大圖、Rxjava、面經
高效加載大圖
給 Android 開發者的 RxJava 詳解---2) 變換的原理:lift()
一年經驗-有贊面經--RxJava的flatMap和Map的作用
總結
以上是生活随笔為你收集整理的一些知识点的整理以及面试题记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebVie打开woffice文档
- 下一篇: Python任务调度模块 – APSch