Android瑣碎知識點(diǎn)小記

  1. 調(diào)用下面的方法,得到的返回值是什么萎战?
public int getNum() {
        try {
            int a = 1 / 0;
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            return 3;
        }
    }

代碼在走到第 3 行的時(shí)候遇到了一個(gè) MathException,這時(shí)第四行的代碼就不會(huì)執(zhí)行了,代碼直接跳轉(zhuǎn)到catch 語句中重斑,走到第 6 行的時(shí)候扒披,異常機(jī)制有這么一個(gè)原則“如果在 catch 中遇到了 return 或者異常等能使該函數(shù)終止的話值依,那么用 finally 就必須先執(zhí)行完 finally 代碼塊里面的代碼然后再返回值〉福”因此代碼又跳到第 8行愿险,可惜第 8 行是一個(gè) return 語句,那么這個(gè)時(shí)候方法就結(jié)束了价说,因此第 6 行的返回結(jié)果就無法被真正返回辆亏。如果 finally 僅僅是處理了一個(gè)釋放資源的操作,那么該道題最終返回的結(jié)果就是 2鳖目。因此上面返回值是 3扮叨。

  1. Java 的基本數(shù)據(jù)類型都有哪些各占幾個(gè)字節(jié)?
    Java 有 8 種基本數(shù)據(jù)類型
    byte 1
    char 2
    sort 2
    int 4
    float 4
    double 8
    long 8
    boolean 1(boolean 類型比較特別可能只占一個(gè) bit领迈,多個(gè) boolean 可能共同占用一個(gè)字節(jié))

  2. String 是基本數(shù)據(jù)類型嗎彻磁?可以被繼承嗎?
    String是引用類型狸捅,底層是用char數(shù)組實(shí)現(xiàn)的衷蜓,String是final類,java 中被final修飾的類不能被繼承尘喝,所以String不能被繼承磁浇。

  3. 在 java 中 wait 和 sleep 方法的不同?
    最大的不同是wait會(huì)釋放鎖瞧省,sleep會(huì)一直持有鎖扯夭。wait通常用于線程間交互,sleep用于暫停執(zhí)行鞍匾。

  4. 什么是線程池交洗,如何使用?
    線程池就是事先將多個(gè)線程對象放到一個(gè)容器里橡淑,當(dāng)使用的時(shí)候就不用new而是直接去線程池中拿線程即可构拳,節(jié)省了開辟子線程的時(shí)間,提高了代碼的執(zhí)行效率。
    在 JDK 的 java.util.concurrent.Executors 中提供了生成多種線程池的靜態(tài)方法置森。

ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);
ScheduledExecutorService newScheduledThreadPool =
Executors.newScheduledThreadPool(4);
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor(); 

然后調(diào)用他們的 execute 方法即可斗埂。

  1. Java 中的反射
    說說你對 Java 中反射的理解?
    Java 中 的 反 射 首 先 是 能 夠 獲 取 到 Java 中 要 反 射 類 的 字 節(jié) 碼 , 獲 取 字 節(jié) 碼 有 三 種 方 法 :1.Class.forName(className) 2.類名.class 3.this.getClass()凫海。然后將字節(jié)碼中的方法呛凶,變量,構(gòu)造函數(shù)等映射成相應(yīng)的 Method行贪、Filed漾稀、Constructor 等類,這些類提供了豐富的方法可以被我們所使用建瘫。
  2. Java 中的動(dòng)態(tài)代理
    寫一個(gè) ArrayList 的動(dòng)態(tài)代理類
final List<String> list = new ArrayList<String>();
 List<String> proxyInstance = (List<String>)
Proxy.newProxyInstance(list.getClass().getClassLoader(),
list.getClass().getInterfaces(), new InvocationHandler() {
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
 return method.invoke(list, args);
 }
 });
 proxyInstance.add("你好");
 System.out.println(list); 
  1. Java 中的設(shè)計(jì)模式
    Java 中一般認(rèn)為有 23 種設(shè)計(jì)模式崭捍,我們不需要所有的都會(huì),但是其中常用的幾種設(shè)計(jì)模式應(yīng)該去掌握啰脚。下面列
    出了所有的設(shè)計(jì)模式殷蛇。需要掌握的設(shè)計(jì)模式我單獨(dú)列出來了,當(dāng)然能掌握的越多越好橄浓。
    總體來說設(shè)計(jì)模式分為三大類:
    創(chuàng)建型模式粒梦,共五種:工廠方法模式、抽象工廠模式荸实、單例模式谍倦、建造者模式、原型模式泪勒。
    結(jié)構(gòu)型模式昼蛀,共七種:適配器模式、裝飾器模式圆存、代理模式叼旋、外觀模式、橋接模式沦辙、組合模式夫植、享元模式。
    行為型模式油讯,共十一種:策略模式详民、模板方法模式、觀察者模式陌兑、迭代子模式沈跨、責(zé)任鏈模式、命令模式兔综、備忘錄
    模式饿凛、狀態(tài)模式狞玛、訪問者模式、中介者模式涧窒、解釋器模式心肪。
  2. 寫 10 個(gè)簡單的 linux 命令
    mkdir 創(chuàng)建文件夾
    rmdir 刪除文件夾
    rm 刪除文件
    mv 移動(dòng)文件
    cp 拷貝文件
    cat 查看文件
    tail 查看文件尾部
    more 分頁查看文件
    cd 切換當(dāng)前目錄
    ls 列出文件清單
    reboot 重啟
    date 顯示日期
    cal 顯示日歷
    ps 查看系統(tǒng)進(jìn)程相當(dāng)于 windows 的任務(wù)管理器
    ifconfig 配置網(wǎng)絡(luò)
  3. Service 是否在 main thread 中執(zhí)行, service 里面是否能執(zhí)行耗時(shí)的操作?
    默認(rèn)情況,如果沒有顯示的指 service 所運(yùn)行的進(jìn)程, Service 和 activity 是運(yùn)行在當(dāng)前 app 所在進(jìn)程的 main thread(UI 主線程)里面。service 里面不能執(zhí)行耗時(shí)的操作(網(wǎng)絡(luò)請求,拷貝數(shù)據(jù)庫,大文件 )
    特殊情況 ,可以在清單文件配置 service 執(zhí)行所在的進(jìn)程 ,讓 service 在另外的進(jìn)程中執(zhí)行纠吴。
<service android:name="com.baidu.location.f"
 android:enabled="true"
 android:process=":remote" ></service> 
  1. Serializable 和 Parcelable 的區(qū)別
    1.在使用內(nèi)存的時(shí)候硬鞍,Parcelable類會(huì)比Serializable性能高,所以推薦使用Parcelable戴已。
    2.Serializable在進(jìn)行序列化的時(shí)候會(huì)產(chǎn)生大量的臨時(shí)變量膳凝,從而引起頻繁的GC。
    3.Parcelable 不能使用在要將數(shù)據(jù)存儲在磁盤上的情況恭陡。盡管 Serializable 效率低點(diǎn),但在這種情況下上煤,還是建議你用 Serializable 休玩。
    實(shí)現(xiàn):
    Serializable 的實(shí)現(xiàn),只需要繼承 Serializable 即可劫狠。這只是給對象打了一個(gè)標(biāo)記拴疤,系統(tǒng)會(huì)自動(dòng)將其序列化。
    Parcelabel 的實(shí)現(xiàn)独泞,需要在類中添加一個(gè)靜態(tài)成員變量 CREATOR呐矾,這個(gè)變量需要繼承 Parcelable.Creator 接
    口。
public class MyParcelable implements Parcelable {
 private int mData;
 public int describeContents() {
 return 0;
 }
 public void writeToParcel(Parcel out, int flags) {
 out.writeInt(mData);
 }
 public static final Parcelable.Creator<MyParcelable> CREATOR= new Parcelable.Creator<MyParcelable>() {
 public MyParcelable createFromParcel(Parcel in) {
 return new MyParcelable(in);
 }
 public MyParcelable[] newArray(int size) {
 return new MyParcelable[size];
 }
 };
 private MyParcelable(Parcel in) {
 mData = in.readInt();
 }
}
  1. 請描述一下 Intent 和 IntentFilter
    Android 中通過 Intent 對象來表示一條消息懦砂,一個(gè) Intent 對象不僅包含有這個(gè)消息的目的地蜒犯,還可以包含消息的內(nèi)容,這好比一封 Email荞膘,其中不僅應(yīng)該包含收件地址罚随,還可以包含具體的內(nèi)容。對于一個(gè) Intent 對象羽资,消息“目的地”是必須的淘菩,而內(nèi)容則是可選項(xiàng)。
    通過 Intent 可以實(shí)現(xiàn)各種系統(tǒng)組件的調(diào)用與激活.
    IntentFilter: 可以理解為郵局或者是一個(gè)信箋的分揀系統(tǒng).
    這個(gè)分揀系統(tǒng)通過 3 個(gè)參數(shù)來識別 :
    Action: 動(dòng)作 view
    Data: 數(shù)據(jù) uri uri
    Category : 而外的附加信息
  2. Fragment 跟 Activity 之間是如何傳值的
    當(dāng) Fragment 跟 Activity 綁定之后屠升,在 Fragment 中可以直接通過 getActivity()方法獲取到其綁定的 Activity對象潮改,這樣就可以調(diào)用 Activity 的方法了。在 Activity 中可以通過如下方法獲取Fragment 實(shí)例 腹暖。
FragmentManager fragmentManager = getFragmentManager();
 Fragment fragment = fragmentManager.findFragmentByTag(tag);
 Fragment fragment = fragmentManager.findFragmentById(id); 

獲取到 Fragment 之后就可以調(diào)用 Fragment 的方法汇在。也就實(shí)現(xiàn)了通信功能。

  1. 如何避免 OOM 異常
    1脏答、圖片過大導(dǎo)致 OOM
    Android 中用 bitmap 時(shí)很容易內(nèi)存溢出趾疚,比如報(bào)如下錯(cuò)誤:Java.lang.OutOfMemoryError : bitmap size exceeds VM budget
    解決方法:
    方法 1: 等比例縮小圖片
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
//Options 只保存圖片尺寸大小缨历,不保存圖片到內(nèi)存
 BitmapFactory.Options opts = new BitmapFactory.Options();
 opts.inSampleSize = 2;
 Bitmap bmp = null;
 bmp = BitmapFactory.decodeResource(getResources(),
mImageIds[position],opts);
 //回收
 bmp.recycle();

以上代碼可以優(yōu)化內(nèi)存溢出,但它只是改變圖片大小糙麦,并不能徹底解決內(nèi)存溢出
方法 2:對圖片采用軟引用辛孵,及時(shí)地進(jìn)行 recyle()操作

SoftReference<Bitmap> bitmap = new SoftReference<Bitmap>(pBitmap);
if(bitmap != null){
if(bitmap.get() != null && !bitmap.get().isRecycled()){
 bitmap.get().recycle();
 bitmap = null;
 }
}

2、界面切換導(dǎo)致 OOM
有時(shí)候我們會(huì)發(fā)現(xiàn)這樣的問題赡磅,橫豎屏切換 N 次后 OOM 了魄缚。
2.1、看看頁面布局當(dāng)中有沒有大的圖片焚廊,比如背景圖之類的冶匹。
去除 xml 中相關(guān)設(shè)置,改在程序中設(shè)置背景圖(放在 onCreate()方法中):

Drawable drawable = getResources().getDrawable(R.drawable.id);
 ImageView imageView = new ImageView(this);
 imageView.setBackgroundDrawable(drawable); 

在 Activity destory 時(shí)注意咆瘟,drawable.setCallback(null); 防止 Activity 得不到及時(shí)的釋放.
2.2 嚼隘、 跟 上 面 方 法 相 似 , 直 接 把 xml 配 置 文 件 加 載 成 view 再 放 到 一 個(gè) 容 器 里 袒餐, 然 后 直 接 調(diào) 用
this.setContentView(View view);方法飞蛹,避免 xml 的重復(fù)加載。
2.3灸眼、 在頁面切換時(shí)盡可能少地重復(fù)使用一些代碼
比如:重復(fù)調(diào)用數(shù)據(jù)庫卧檐,反復(fù)使用某些對象等等......
常見的內(nèi)存使用不當(dāng)?shù)那闆r
3、查詢數(shù)據(jù)庫沒有關(guān)閉游標(biāo) 查詢數(shù)據(jù)庫沒有關(guān)閉游標(biāo) 查詢數(shù)據(jù)庫沒有關(guān)閉游標(biāo)
程序中經(jīng)常會(huì)進(jìn)行查詢數(shù)據(jù)庫的操作焰宣,但是經(jīng)常會(huì)有使用完畢 Cursor 后沒有關(guān)閉的情況霉囚。如果我們的查詢結(jié)果集比較小,對內(nèi)存的消耗不容易被發(fā)現(xiàn)匕积,只有在常時(shí)間大量操作的情況下才會(huì)出現(xiàn)內(nèi)存問題盈罐,這樣就會(huì)給以后的測試和問題排查帶來困難和風(fēng)險(xiǎn)。
4闪唆、構(gòu)造 Adapter Adapter Adapter 時(shí)暖呕,沒有使用緩存的 沒有使用緩存的 沒有使用緩存的convertView convertView convertView
在使用 ListView 的時(shí)候通常會(huì)使用 Adapter,那么我們應(yīng)該盡可能的使用 ConvertView苞氮。
5湾揽、Bitmap 對象不再使用時(shí)調(diào)用 對象不再使用時(shí)調(diào)用 對象不再使用時(shí)調(diào)用 recycle() recycle() recycle()釋放內(nèi)存.
有時(shí)我們會(huì)手工的操作 Bitmap 對象,如果一個(gè) Bitmap 對象比較占內(nèi)存笼吟,當(dāng)它不再被使用的時(shí)候库物,可以調(diào)用Bitmap.recycle()方法回收此對象的像素所占用的內(nèi)存,但這不是必須的贷帮,視情況而定戚揭。
6、其他
Android 應(yīng)用程序中最典型的需要注意釋放資源的情況是在 Activity 的生命周期中撵枢,在 onPause()民晒、onStop()精居、onDestroy()方法中需要適當(dāng)?shù)尼尫刨Y源的情況。

  1. Android 中如何捕獲未捕獲的異常
    1潜必、自定義一個(gè) Application靴姿,比如叫 MyApplication 繼承 Application 實(shí)現(xiàn) UncaughtExceptionHandler。
    2磁滚、覆寫 UncaughtExceptionHandler 的 onCreate 和 uncaughtException 方法佛吓。
@Override
public void onCreate() {
 super.onCreate();
 Thread.setDefaultUncaughtExceptionHandler(this);
 }
@Override
public void uncaughtException(final Thread thread, final Throwable ex) {
 new Thread(new Runnable() {

 @Override
 public void run() {
 Looper.prepare();
 System.out.println(Thread.currentThread());
 Toast.makeText(getApplicationContext(), "thread="+thread.getId()+"
ex="+ex.toString(), 1).show();
 Looper.loop();
 }
 }).start();
 SystemClock.sleep(3000);
 android.os.Process.killProcess(android.os.Process.myPid());
 }
} 

注意:上面的代碼只是簡單的將異常打印出來。
在 onCreate 方法中我們給 Thread 類設(shè)置默認(rèn)異常處理 handler垂攘,如果這句代碼不執(zhí)行則一切都是白搭维雇。
在 uncaughtException 方法中我們必須新開辟個(gè)線程進(jìn)行我們異常的收集工作,然后將系統(tǒng)給殺死.
3晒他、在 AndroidManifest 中配置該 Application

<application
 android:name="com.example.uncatchexception.MyApplication"/>
  1. 請描述一下 View 的繪制流程
    整個(gè) View 樹的繪圖流程是在 ViewRoot.java 類(該類位于 Android 源碼下面:
    D:\AndroidSource_GB\AndroidSource_GB\frameworks\base\core\java\android\view)的performTraversals()函數(shù)展開的,該函數(shù)做的執(zhí)行過程可簡單概況為根據(jù)之前設(shè)置的狀態(tài)吱型,判斷是否需要重新計(jì)算視圖大小(measure)、是否重新需要安置視圖的位置(layout)陨仅、以及是否需要重繪 (draw)津滞,其框架過程如下:
338650C6-00C1-4962-B083-400880D506F6.png

由 ViewRoot 對象的 performTraversals()方法調(diào)用 draw()方法發(fā)起繪制該 View 樹,值得注意的是每次發(fā)起繪
圖時(shí)掂名,并不會(huì)重新繪制每個(gè) View 樹的視圖,而只會(huì)重新繪制那些“需要重繪”的視圖哟沫,View 類內(nèi)部變量包含了一個(gè)
標(biāo)志位 DRAWN饺蔑,當(dāng)該視圖需要重繪時(shí),就會(huì)為該 View 添加該標(biāo)志位嗜诀。

  1. Handler 機(jī)制
    Android 中主線程也叫 UI 線程猾警,那么從名字上我們也知道主線程主要是用來創(chuàng)建、更新 UI 的隆敢,而其他耗時(shí)操作发皿,比如網(wǎng)絡(luò)訪問,或者文件處理拂蝎,多媒體處理等都需要在子線程中操作穴墅,之所以在子線程中操作是為了保證 UI 的流暢程度,手機(jī)顯示的刷新頻率是 60Hz温自,也就是一秒鐘刷新 60 次玄货,每 16.67 毫秒刷新一次,為了不丟幀悼泌,那么主線程處理代碼最好不要超過 16 毫秒松捉。當(dāng)子線程處理完數(shù)據(jù)后,為了防止 UI 處理邏輯的混亂馆里,Android 只允許主線程修改 UI隘世,那么這時(shí)候就需要 Handler 來充當(dāng)子線程和主線程之間的橋梁了可柿。我們通常將 Handler 聲明在 Activity 中,然后覆寫 Handler 中的 handleMessage 方法,當(dāng)子線程調(diào)用handler.sendMessage()方法后 handleMessage 方法就會(huì)在主線程中執(zhí)行丙者。這里面除了 Handler复斥、Message 外還有隱藏的 Looper 和 MessageQueue 對象。
    在主線程中 Android 默認(rèn)已經(jīng)調(diào)用了 Looper.preper()方法蔓钟,調(diào)用該方法的目的是在 Looper 中創(chuàng)建MessageQueue 成員變量并把 Looper 對象綁定到當(dāng)前線程中永票。當(dāng)調(diào)用 Handler sendMessage(對象)方法的時(shí)候就將 Message 對象添加到了 Looper 創(chuàng)建的 MessageQueue 隊(duì)列中,同時(shí)給 Message 指定了 target 對象滥沫,其實(shí)這個(gè) target 對象就是 Handler 對象侣集。主線程默認(rèn)執(zhí)行了Looper.looper()方法,該方法從 Looper 的成員變量MessageQueue 中取出 Message兰绣,然后調(diào)用 Message 的 target 對象的 handleMessage()方法世分。這樣就完成了整個(gè)消息機(jī)制。

  2. 事件分發(fā)中的 2.1 事件分發(fā)中的 onTouch onTouch onTouch 和 onTouchEvent onTouchEvent onTouchEvent 有什么區(qū)別缀辩,又該如何使用臭埋?
    這兩個(gè)方法都是在 View 的 dispatchTouchEvent 中調(diào)用的onTouch 優(yōu)先于 onTouchEvent 執(zhí)行。如果在onTouch 方法中通過返回 true 將事件消費(fèi)掉臀玄,onTouchEvent 將不會(huì)再執(zhí)行瓢阴。
    另外需要注意的是,onTouch 能夠得到執(zhí)行需要兩個(gè)前提條件健无,第一 mOnTouchListener 的值不能為空荣恐,第二當(dāng)前點(diǎn)擊的控件必須是 enable 的。因此如果你有一個(gè)控件是非 enable 的累贤,那么給它注冊 onTouch 事件將永遠(yuǎn)得不到執(zhí)行叠穆。對于這一類控件,如果我們想要監(jiān)聽它的 touch 事件臼膏,就必須通過在該控件中重寫 onTouchEvent 方法來實(shí)現(xiàn)硼被。

  3. 講一下android中進(jìn)程的優(yōu)先級?
    前臺進(jìn)程
    可見進(jìn)程
    服務(wù)進(jìn)程
    后臺進(jìn)程
    空進(jìn)程

  4. Map渗磅、Set嚷硫、List、Queue始鱼、Stack的特點(diǎn)與用法论巍。
    Collection 是對象集合, Collection 有兩個(gè)子接口 List 和 Set
    List 可以通過下標(biāo) (1,2..) 來取得值风响,值可以重復(fù)嘉汰。
    而 Set 只能通過游標(biāo)來取值,并且值是不能重復(fù)的状勤。
    ArrayList 鞋怀, Vector 双泪, LinkedList 是 List 的實(shí)現(xiàn)類。
    ArrayList 是線程不安全的密似, Vector 是線程安全的焙矛,這兩個(gè)類底層都是由數(shù)組實(shí)現(xiàn)的。
    LinkedList 是線程不安全的残腌,底層是由鏈表實(shí)現(xiàn)的村斟。
    Map 是鍵值對集合:
    HashTable 和 HashMap 是 Map 的實(shí)現(xiàn)類。
    HashTable 是線程安全的抛猫,不能存儲 null 值蟆盹。
    HashMap 不是線程安全的,可以存儲 null 值闺金。
    Stack類:繼承自Vector逾滥,實(shí)現(xiàn)一個(gè)后進(jìn)先出的棧。提供了幾個(gè)基本方法败匹,push寨昙、pop、peak掀亩、empty舔哪、search等。
    Queue接口:提供了幾個(gè)基本方法槽棍,offer捉蚤、poll、peek等刹泄。已知實(shí)現(xiàn)類有LinkedList外里、PriorityQueue等怎爵。
    21.Java中==和equals的區(qū)別特石,equals和hashCode的區(qū)別
    java中的數(shù)據(jù)類型,可分為兩類:
    a. 基本數(shù)據(jù)類型:byte short long int char double boolean float .它們之間的比較應(yīng)當(dāng)用(==)鳖链,比較的是他們的值姆蘸。
    b. 復(fù)合數(shù)據(jù)類型(類) :當(dāng)他們用(==)進(jìn)行比較的時(shí)候,比較的是他們在內(nèi)存中的存放地址芙委,所以逞敷,除非是同一個(gè)new出來的對象,他們的比較后的結(jié)果為true灌侣,否則比較后結(jié)果為false推捐。
    equals方法:
    JAVA當(dāng)中所有的類都是繼承于Object這個(gè)基類的,在Object中的基類中定義了一個(gè)equals的方法侧啼,這個(gè)方法的初始行為是比較對象的內(nèi)存地址牛柒,但在一些類庫當(dāng)中這個(gè)方法被覆蓋掉了堪簿,如String,Integer,Date在這些類當(dāng)中equals有其自身的實(shí)現(xiàn),而不再是比較類在堆內(nèi)存中的存放地址了皮壁。
    hashCode 方法:
    如果兩個(gè)對象根據(jù)equals()方法比較是相等的椭更,那么調(diào)用這兩個(gè)對象中任意一個(gè)對象的hashCode方法都必須產(chǎn)生同樣的整數(shù)結(jié)果例获。
    如果兩個(gè)對象根據(jù)equals()方法比較是不相等的屁药,那么調(diào)用這兩個(gè)對象中任意一個(gè)對象的hashCode方法,則不一定要產(chǎn)生相同的整數(shù)結(jié)果敌厘。
    從而在集合操作的時(shí)候有如下規(guī)則:
    將對象放入到集合中時(shí)滴须,首先判斷要放入對象的hashcode值與集合中的任意一個(gè)元素的hashcode值是否相等舌狗,如果不相等直接將該對象放入集合中。如果hashcode值相等描馅,然后再通過equals方法判斷要放入對象與集合中的任意一個(gè)對象是否相等把夸,如果equals判斷不相等,直接將該元素放入到集合中铭污,否則不放入恋日。

Android性能優(yōu)化

  1. 節(jié)制的使用Service,當(dāng)啟動(dòng)一個(gè)Service時(shí),系統(tǒng)會(huì)傾向于將這個(gè)Service所依賴的進(jìn)程進(jìn)行保留嘹狞,系統(tǒng)可以在LRUcache當(dāng)中緩存的進(jìn)程數(shù)量也會(huì)減少岂膳,導(dǎo)致切換程序的時(shí)候耗費(fèi)更多性能。我們可以使用IntentService磅网,當(dāng)后臺任務(wù)執(zhí)行結(jié)束后會(huì)自動(dòng)停止谈截,避免了Service的內(nèi)存泄漏。
    知曉內(nèi)存的開支情況
  • 使用枚舉通常會(huì)比使用靜態(tài)常量消耗兩倍以上的內(nèi)存涧偷,盡可能不使用枚舉
  • 任何一個(gè)Java類簸喂,包括匿名類、內(nèi)部類燎潮,都要占用大概500字節(jié)的內(nèi)存空間
  • 任何一個(gè)類的實(shí)例要消耗12-16字節(jié)的內(nèi)存開支喻鳄,因此頻繁創(chuàng)建實(shí)例也是會(huì)在一定程序上影響內(nèi)存的
  • 使用HashMap時(shí),即使你只設(shè)置了一個(gè)基本數(shù)據(jù)類型的鍵确封,比如說int除呵,但是也會(huì)按照對象的大小來分配內(nèi)存,大概是32字節(jié)爪喘,而不是4字節(jié)颜曾,因此最好使用優(yōu)化后的數(shù)據(jù)集合
    避免創(chuàng)建不必要的對象
  • 如果有需要拼接的字符串,那么可以優(yōu)先考慮使用StringBuffer或者StringBuilder來進(jìn)行拼接秉剑,而不是加號連接符泛豪,因?yàn)槭褂眉犹栠B接符會(huì)創(chuàng)建多余的對象,拼接的字符串越長,加號連接符的性能越低诡曙。
  • 當(dāng)一個(gè)方法的返回值是String的時(shí)候吕粹,通常需要去判斷一下這個(gè)String的作用是什么,如果明確知道調(diào)用方會(huì)將返回的String再進(jìn)行拼接操作的話岗仑,可以考慮返回一個(gè)StringBuffer對象來代替匹耕,因?yàn)檫@樣可以將一個(gè)對象的引用進(jìn)行返回,而返回String的話就是創(chuàng)建了一個(gè)短生命周期的臨時(shí)對象荠雕。
  • 在沒有特殊原因的情況下稳其,盡量使用基本數(shù)據(jù)類型來代替封裝數(shù)據(jù)類型,int比Integer要更加有效炸卑,其它數(shù)據(jù)類型也是一樣既鞠。
    僅在需要時(shí)才加載布局
    舉例:填信息時(shí)不是需要全部填的,有一個(gè)添加更多字段的選項(xiàng)盖文,當(dāng)用戶需要添加其他信息的時(shí)候嘱蛋,才將另外的元素顯示到界面上。用VISIBLE性能表現(xiàn)一般五续,可以用ViewStub洒敏。ViewStub也是View的一種,但是沒有大小疙驾,沒有繪制功能凶伙,也不參與布局,資源消耗非常低它碎,可以認(rèn)為完全不影響性能函荣。
<ViewStub   
        android:id="@+id/view_stub"  
        android:layout="@layout/profile_extra"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        />  
public void onMoreClick() {  
    ViewStub viewStub = (ViewStub) findViewById(R.id.view_stub);  
    if (viewStub != null) {  
        View inflatedView = viewStub.inflate();  
        editExtra1 = (EditText) inflatedView.findViewById(R.id.edit_extra1);  
        editExtra2 = (EditText) inflatedView.findViewById(R.id.edit_extra2);  
        editExtra3 = (EditText) inflatedView.findViewById(R.id.edit_extra3);  
    }  
}  

為什么在Service中創(chuàng)建子線程而不是Activity中?

這是因?yàn)锳ctivity很難對Thread進(jìn)行控制,當(dāng)Activity被銷毀之后扳肛,就沒有任何其它的辦法可以再重新獲取到之前創(chuàng)建的子線程的實(shí)例傻挂。而且在一個(gè)Activity中創(chuàng)建的子線程,另一個(gè)Activity無法對其進(jìn)行操作挖息。但是Service就不同了金拒,所有的Activity都可以與Service進(jìn)行關(guān)聯(lián),然后可以很方便地操作其中的方法旋讹,即使Activity被銷毀了殖蚕,之后只要重新與Service建立關(guān)聯(lián)轿衔,就又能夠獲取到原有的Service中Binder的實(shí)例沉迹。因此,使用Service來處理后臺任務(wù)害驹,Activity就可以放心地finish鞭呕,完全不需要擔(dān)心無法對后臺任務(wù)進(jìn)行控制的情況。

哪些操作會(huì)導(dǎo)致ANR 在主線程執(zhí)行以下操作:

  1. 高耗時(shí)的操作宛官,如圖像變換 2. 磁盤讀寫葫松,數(shù)據(jù)庫讀寫操作 3. 大量的創(chuàng)建新對象
    String瓦糕、StringBuilder、StringBuffer腋么、CharSequence區(qū)別
    1)CharSequence接口:是一個(gè)字符序列.String StringBuilder 和 StringBuffer都實(shí)現(xiàn)了它.
  1. String類:是常量,不可變.
  2. StringBuilder類;只可以在單線程的情況下進(jìn)行修改(線程不安全).
  3. StringBuffer類:可以在多線程的情況下進(jìn)行改變(線程安全). 5)Stringbuilder比StringBuffer效率高,應(yīng)該盡量使用StringBuilder.

1.CharSequence是一個(gè)java接口咕娄,代表一個(gè)char序列,String珊擂、StringBuilder圣勒、StringBuffer都實(shí)現(xiàn)了該接口,CharSequence實(shí)例通過調(diào)用toString方法可轉(zhuǎn)化為String對象摧扇。
2.String類是final的圣贸,不可派生子類,其內(nèi)部封裝的是char[]扛稽,另外吁峻,android下的String類和jdk中的String類是有區(qū)別的,android下的String類中部分API通過native方法實(shí)現(xiàn)在张,效率相對高一些用含。
3.String使用'+'進(jìn)行字符串拼接時(shí),在編譯期會(huì)轉(zhuǎn)化為StringBuilder#append方式
4.String在內(nèi)存中有一個(gè)常量池帮匾,兩個(gè)相同的串在池中只有一份實(shí)例(String s = "abc"方式或者String#intern方式會(huì)在池中分配)耕餐,使用new String方式會(huì)在heap中分配,每次創(chuàng)建都是一個(gè)全新的實(shí)例辟狈。
5.StrigBuilder & StringBuffer都是可擴(kuò)展的串肠缔,提供了一系列apped方法用于拼接不同類型對象
6.StringBuffer于jdk1.0引入,線程安全(多線程場景下使用)哼转,StringBuilder于jdk1.5引入明未,線程不安全,因而效率更高壹蔓。
7.StringBuilder & StringBuffer初始容量都為16趟妥,開發(fā)者應(yīng)該指定其容量,以避免多次擴(kuò)容所帶來的性能問題佣蓉。

要做一個(gè)盡可量流暢的ListView披摄,你可以做到的優(yōu)化手段是什么?越詳細(xì)越多手段越好

復(fù)用convertView
使用ViewHolder
滑動(dòng)時(shí)不加載圖片
Item中有圖片時(shí) 異步加載 并且對圖片進(jìn)行適當(dāng)壓縮
分批勇凭,分頁加載

Java中反射的作用是什么?什么時(shí)候會(huì)用到

對于任意一個(gè)類疚膊,都能夠知道這個(gè)類的所有屬性和方法;
對于任意一個(gè)對象寓盗,都能夠調(diào)用它的任意一個(gè)方法;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對象的方法的功能稱為java語言的反射機(jī)制基显。
Java反射機(jī)制主要提供了以下功能:
a)在運(yùn)行時(shí)判斷任意一個(gè)對象所屬的類;
b)在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對象善炫;
c)在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法撩幽;
d)在運(yùn)行時(shí)調(diào)用任意一個(gè)對象的方法摸航;生成動(dòng)態(tài)代理。

Java中有內(nèi)存泄露嗎舅桩?舉一些例子酱虎?

1.查詢數(shù)據(jù)庫沒有關(guān)閉游標(biāo)

  1. 構(gòu)造Adapter時(shí)擂涛,沒有使用緩存的 convertView
  2. Bitmap對象不再使用時(shí)調(diào)用recycle()釋放內(nèi)存
  3. 無用時(shí)沒有釋放對象的引用
  4. 在Activity中使用非靜態(tài)的內(nèi)部類,并開啟一個(gè)長時(shí)間運(yùn)行的線程恢暖,因?yàn)閮?nèi)部類持有Activity的引用狰右,會(huì)導(dǎo)致Activity本來可以被gc時(shí)卻長期得不到回收
    6.使用Handler處理消息前,Activity通過例如finish()退出嫁佳,導(dǎo)致內(nèi)存泄漏
    7.動(dòng)態(tài)注冊廣播在Activity銷毀前沒有unregisterReceiver
    如何縮減APK包大小
    代碼
    保持良好的編程習(xí)慣谷暮,不要重復(fù)或者不用的代碼湿弦,謹(jǐn)慎添加libs,移除使用不到的libs颊埃。
    使用proguard混淆代碼,它會(huì)對不用的代碼做優(yōu)化饥漫,并且混淆后也能夠減少安裝包的大小肥败。
    native code的部分,大多數(shù)情況下只需要支持armabi與x86的架構(gòu)即可馒稍。如果非必須皿哨,可以考慮拿掉x86的部分纽谒。
    資源
    使用Lint工具查找沒有使用到的資源。去除不使用的圖片央勒,String澳化,XML等等缎谷。
    assets目錄下的資源請確保沒有用不上的文件。
    生成APK的時(shí)候瑞你,aapt工具本身會(huì)對png做優(yōu)化希痴,但是在此之前還可以使用其他工具如tinypng對圖片進(jìn)行進(jìn)一步的壓縮預(yù)處理砌创。
    jpeg還是png,根據(jù)需要做選擇寇钉,在某些時(shí)候jpeg可以減少圖片的體積扫倡。
    對于9.png的圖片竟纳,可拉伸區(qū)域盡量切小锥累,另外可以通過使用9.png拉伸達(dá)到大圖效果的時(shí)候盡量不要使用整張大圖。
    策略
    有選擇性的提供hdpi语淘,xhdpi,xxhdpi的圖片資源姑蓝。建議優(yōu)先提供xhdpi的圖片纺荧,對于mdpi颅筋,ldpi與xxxhdpi根據(jù)需要提供有差異的部分即可议泵。
    盡可能的重用已有的圖片資源。例如對稱的圖片靶剑,只需要提供一張池充,另外一張圖片可以通過代碼旋轉(zhuǎn)的方式實(shí)現(xiàn)收夸。
    能用代碼繪制實(shí)現(xiàn)的功能,盡量不要使用大量的圖片厘灼。例如減少使用多張圖片組成animate-list的AnimationDrawable设凹,這種方式提供了多張圖片很占空間茅姜。

聲明ViewHolder內(nèi)部類時(shí)钻洒,為什么建議使用static關(guān)鍵字

這個(gè)是考靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類的主要區(qū)別之一。非靜態(tài)內(nèi)部類會(huì)隱式持有外部類的引用称诗,就像大家經(jīng)常將自定義的adapter在Activity類里寓免,然后在adapter類里面是可以隨意調(diào)用外部activity的方法的。當(dāng)你將內(nèi)部類定義為static時(shí)撕予,你就調(diào)用不了外部類的實(shí)例方法了嗅蔬,因?yàn)檫@時(shí)候靜態(tài)內(nèi)部類是不持有外部類的引用的疾就。聲明ViewHolder靜態(tài)內(nèi)部類猬腰,可以將ViewHolder和外部類解引用猜敢。大家會(huì)說一般ViewHolder都很簡單缩擂,不定義為static也沒事吧。確實(shí)如此懈费,但是如果你將它定義為static的憎乙,說明你懂這些含義叉趣。萬一有一天你在這個(gè)ViewHolder加入一些復(fù)雜邏輯疗杉,做了一些耗時(shí)工作,那么如果ViewHolder是非靜態(tài)內(nèi)部類的話椭蹄,就很容易出現(xiàn)內(nèi)存泄露绳矩。如果是靜態(tài)的話玖翅,你就不能直接引用外部類,迫使你關(guān)注如何避免相互引用严沥。 所以將 ViewHolder內(nèi)部類 定義為靜態(tài)的中姜,是一種好習(xí)慣.

java是如何管理內(nèi)存的

Java的內(nèi)存管理就是對象的分配和釋放問題丢胚。(兩部分)

分配 :內(nèi)存的分配是由程序完成的携龟,程序員需要通過關(guān)鍵字new 為每個(gè)對象申請內(nèi)存空間 (基本類型除外),所有的對象都在堆 (Heap)中分配空間坟桅。

釋放 :對象的釋放是由垃圾回收機(jī)制決定和執(zhí)行的仅乓,這樣做確實(shí)簡化了程序員的工作蓬戚。但同時(shí)碌更,它也加重了JVM的工作。因?yàn)楹偌珿C為了能夠正確釋放對象鸟妙,GC必須監(jiān)控每一個(gè)對象的運(yùn)行狀態(tài)重父,包括對象的申請忽匈、引用丹允、被引用袋倔、賦值等宾娜,GC都需要進(jìn)行監(jiān)控前塔。

JVM的內(nèi)存區(qū)域組成

java把內(nèi)存分兩種:一種是棧內(nèi)存承冰,另一種是堆內(nèi)存
1巷懈。在函數(shù)中定義的基本類型變量和對象的引用變量都在函數(shù)的棧內(nèi)存中分配慌洪;
2冈爹。堆內(nèi)存用來存放由new創(chuàng)建的對象和數(shù)組以及對象的實(shí)例變量 在函數(shù)(代碼塊)中定義一個(gè)變量時(shí)频伤,java就在棧中為這個(gè)變量分配內(nèi)存空間憋肖,當(dāng)超過變量的作用域后,java會(huì)自動(dòng)釋放掉為該變量所分配的內(nèi)存空間鸵膏;在堆中分配的內(nèi)存由java虛擬機(jī)的自動(dòng)垃圾回收器來管理.

堆和棧的優(yōu)缺點(diǎn)
堆的優(yōu)勢是可以動(dòng)態(tài)分配內(nèi)存大小谭企,生存期也不必事先告訴編譯器评肆,因?yàn)樗窃谶\(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存的瓜挽。
缺點(diǎn)就是要在運(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存久橙,存取速度較慢; 棧的優(yōu)勢是颠放,存取速度比堆要快碰凶,僅次于直接位于CPU中的寄存器欲低。
另外,棧數(shù)據(jù)可以共享瑞筐。但缺點(diǎn)是聚假,存在棧中的數(shù)據(jù)大小與生存期必須是確定的膘格,缺乏靈活性财松。

垃圾回收機(jī)制:

(問題一:什么叫垃圾回收機(jī)制辆毡?)
垃圾回收是一種動(dòng)態(tài)存儲管理技術(shù)舶掖,它自動(dòng)地釋放不再被程序引用的對象访锻,按照特定的垃圾收集算法來實(shí)現(xiàn)資源自動(dòng)回收的功能。當(dāng)一個(gè)對象不再被引用的時(shí)候河哑,內(nèi)存回收它占領(lǐng)的空間璃谨,以便空間被后來的新對象使用佳吞,以免造成內(nèi)存泄露。
(問題二:java的垃圾回收有什么特點(diǎn)铸抑?)
JAVA語言不允許程序員直接控制內(nèi)存空間的使用鹊汛。內(nèi)存空間的分配和回收都是由JRE負(fù)責(zé)在后臺自動(dòng)進(jìn)行的,尤其是無用內(nèi)存空間的回收操作(garbagecollection,也稱垃圾回收)至耻,只能由運(yùn)行環(huán)境提供的一個(gè)超級線程進(jìn)行監(jiān)測和控制尘颓。
(問題四:什么樣的對象符合垃圾回收條件泥耀?) 當(dāng)沒有任何獲得線程能訪問一個(gè)對象時(shí),該對象就符合垃圾回收條件兜辞。
(問題五:垃圾回收器是怎樣工作的逸吵?)
垃圾回收器如發(fā)現(xiàn)一個(gè)對象不能被任何活線程訪問時(shí)扫皱,他將認(rèn)為該對象符合刪除條件韩脑,就將其加入回收隊(duì)列段多,但不是立即銷毀對象,何時(shí)銷毀并釋放內(nèi)存是無法預(yù)知的加缘。垃圾回收不能強(qiáng)制執(zhí)行拣宏,然而Java提供了一些方法(如:System.gc()方法)勋乾,允許你請求JVM執(zhí)行垃圾回收,而不是要求杨凑,虛擬機(jī)會(huì)盡其所能滿足請求撩满,但是不能保證JVM從內(nèi)存中刪除所有不用的對象伺帘。
(問題六:一個(gè)java程序能夠耗盡內(nèi)存嗎伪嫁?) 可以张咳。垃圾收集系統(tǒng)嘗試在對象不被使用時(shí)把他們從內(nèi)存中刪除似舵。然而砚哗,如果保持太多活的對象龙助,系統(tǒng)則可能會(huì)耗盡內(nèi)存。垃圾回收器不能保證有足夠的內(nèi)存蛛芥,只能保證可用內(nèi)存盡可能的得到高效的管理提鸟。
(問題七:如何顯示的使對象符合垃圾回收條件?) (1) 空引用 :當(dāng)對象沒有對他可到達(dá)引用時(shí)仅淑,他就符合垃圾回收的條件称勋。也就是說如果沒有對他的引用,刪除對象的引用就可以達(dá)到目的漓糙,因此我們可以把引用變量設(shè)置為null,來符合垃圾回收的條件。
StringBuffer sb = new StringBuffer("hello");
System.out.println(sb);
sb=null;
(2) 重新為引用變量賦值:可以通過設(shè)置引用變量引用另一個(gè)對象來解除該引用變量與一個(gè)對象間的引用關(guān)系蝗蛙。
StringBuffer sb1 = new StringBuffer("hello");
StringBuffer sb2 = new StringBuffer("goodbye");
System.out.println(sb1);
sb1=sb2;//此時(shí)"hello"符合回收條件
(3) 方法內(nèi)創(chuàng)建的對象:所創(chuàng)建的局部變量僅在該方法的作用期間內(nèi)存在蝇庭。一旦該方法返回,在這個(gè)方法內(nèi)創(chuàng)建的對象就符合垃圾收集條件捡硅。有一種明顯的例外情況哮内,就是方法的返回對象。
public static void main(String[] args) {
Date d = getDate();
System.out.println("d = " + d);
}
private static Date getDate() {
Date d2 = new Date();
StringBuffer now = new StringBuffer(d2.toString());
System.out.println(now);
return d2;
}
(4) 隔離引用:這種情況中壮韭,被回收的對象仍具有引用北发,這種情況稱作隔離島。若存在這兩個(gè)實(shí)例喷屋,他們互相引用琳拨,并且這兩個(gè)對象的所有其他引用都刪除,其他任何線程無法訪問這兩個(gè)對象中的任意一個(gè)屯曹。也可以符合垃圾回收條件狱庇。
public class Island {
Island i;
public static void main(String[] args) {
Island i2 = new Island();
Island i3 = new Island();
Island i4 = new Island();
i2.i=i3;
i3.i=i4;
i4.i=i2;
i2=null;
i3=null;
i4=null;
}
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市恶耽,隨后出現(xiàn)的幾起案子密任,更是在濱河造成了極大的恐慌,老刑警劉巖偷俭,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浪讳,死亡現(xiàn)場離奇詭異,居然都是意外死亡涌萤,警方通過查閱死者的電腦和手機(jī)淹遵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來形葬,“玉大人合呐,你說我怎么就攤上這事◇弦裕” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵冻辩,是天一觀的道長猖腕。 經(jīng)常有香客問我,道長恨闪,這世上最難降的妖魔是什么倘感? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮咙咽,結(jié)果婚禮上老玛,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好蜡豹,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布麸粮。 她就那樣靜靜地躺著,像睡著了一般镜廉。 火紅的嫁衣襯著肌膚如雪弄诲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天娇唯,我揣著相機(jī)與錄音齐遵,去河邊找鬼。 笑死塔插,一個(gè)胖子當(dāng)著我的面吹牛梗摇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播想许,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼留美,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伸刃?” 一聲冷哼從身側(cè)響起谎砾,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捧颅,沒想到半個(gè)月后景图,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碉哑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年挚币,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扣典。...
    茶點(diǎn)故事閱讀 38,625評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡妆毕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贮尖,到底是詐尸還是另有隱情笛粘,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布湿硝,位于F島的核電站薪前,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏关斜。R本人自食惡果不足惜示括,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痢畜。 院中可真熱鬧垛膝,春花似錦鳍侣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扔罪,卻和暖如春秉沼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背矿酵。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工唬复, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人全肮。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓敞咧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辜腺。 傳聞我的和親對象是個(gè)殘疾皇子休建,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評論 2 348

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