Android小知識清單(一)

  在公司多人協作寫代碼最怕的就是衝突。。。因此一定要協作好,必須有規範,比如引用的庫v4、v7包版本都要一致等等。

1、invalidate()和postInvalidate()有什麼區別?

        對於invalidate()源碼註釋如下:

     *Invalidate the whole view. If the view is visible,
     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
     * the future. This must be called from a UI thread. To call from a non-UI thread,
     * call {@link #postInvalidate()}. 

   即該方法會導致整個View都無效,然後會調用onDraw()方法,且該方法必須在主線程中使用,如果需要在子線程中調用,我們通常的做法是使用Thread+Handler來完成invalidate()調用,或者使用postInvalidate()方法,此方法可以直接在子Thread中使用。這就是兩者的區別。需要注意的是,如果是在View中調用那麼會導致該View被繪製,而其它視圖不會被繪製,如果是在ViewGroup中調用這兩個方法那麼會導致該ViewGroup下的所有子視圖重繪。

2、Parcelable接口有什麼用?

      此接口源碼解釋如下:

* Interface for classes whose instances can be written to
 * and restored from a {@link Parcel}.  Classes implementing the Parcelable
 * interface must also have a static field called <code>CREATOR</code>, which
 * is an object implementing the {@link Parcelable.Creator Parcelable.Creator}
 * interface.
 *
       此接口用於序列化和反序列化數據,而且性能較Serializable稍微高一些,不過實現也稍微多一個步驟,註釋中已有說明,且源碼還有一個例子,就不貼出來了。值得思考的是Android爲什麼引進一個Parcelable接口呢?我猜測主要還是基於性能考慮吧,Ctrl+T發現framework中實現此接口的類有很多,我目測了下,至少有好幾十個類。典型的有Bundle和ContentValues,所以在Intent傳遞數據的時候我們可以直接傳遞ContentValues,可以直接intent.putExtra(key,cv),獲取時intent.getExtras().get(key)。。。etc.  跑題了!。。那麼framework中有這麼多類都需要序列化存儲數據,爲了提高性能,是很有值得引入一個接口代替Serializable了。實際上Serializable接口中沒啥內容,要被序列化的類實現此接口不過是一個標識,標識該類可以被序列化。同理Parcelable接口也是一樣,不過在序列化時能提高性能,具體沒有研究 - -、,以後有時間了再仔細瞅瞅。

3、xml佈局文件中的"?"和"@"的區別?

  “?”引用主題屬性,當使用這個標記,我們所提供的資源名必須能夠在主題屬性中找到,因爲資源工具認爲這個資源屬性是被期望得到的,我們不需要明確的指出它的類型(也就是不需要寫全在哪個文件中?android:attr/android:textDisabledColor)。

  @表示引用資源文件中我們定義的內容drawable、string等,主題屬性和樣式屬性只是使用範圍不同而已,效果差不多,系統的主題屬性有:http://android.toolib.net/reference/android/R.styleable.html#Theme

4、如何在xml中使用自定義視圖的屬性?

    如果在xml中要引用自定義控件的屬性,必須在xml命名空間引用,比如:xmlns:bar="http://schemas.android.com/apk/res/com.geo.ui",和系統的屬性引用一樣只不過在res目錄後加上自己程序的包名,這個包名不是自定義控件所在的包名,而是在androidmanifest.xml 文件中的package屬性的名字,這個包名就是應用程序的進程名字。當然了“bar”這個名字隨意起。

5、java中map、list如何更快創建對象並添加數據?

public static HashSet<String> sDocMimeTypesSet = new HashSet<String>() {        
{           
 add("text/plain");           
 add("text/plain");            
add("application/pdf");            
add("application/msword");           
 add("application/vnd.ms-excel");           
 add("application/vnd.ms-excel");      
  }  
  };

6、ActionMode是什麼?

    ActionMode是4.0後新特性,表示長按某個視圖就會出現類似菜單上下文的菜單,但不是彈窗,而是在ActionBar上面顯示。要使用ActionMode需要先實現ActionMode.CallBback接口,然後在Activity中調用startActionMode(),或在Fragment中調用getActivity().startActionMode();

7、SQLiteOpenHelper的onCreate()方法調用問題。

    SQLiteOpenHelper的onCreate()方法只在數據庫第一次被創建的時候調用一次,如果該數據庫已經存在就不會重複調用了。因此,如果我們在一個已有的數據庫中新增一個表,就需要在onUpgrade(SQLiteDatabase,int,int)中做數據庫升級。當我們要對數據庫升級的時候,僅僅在onCreate(SQLiteDatabase db)方法中增加一條sql語句和修改版本號是不夠的,還要在onUpgrade()函數中增加要升級的sql語句,不然會導致升級失敗,項目中遇到這個坑。比較詳細的看此博客:http://www.cnblogs.com/liqw/p/4264925.html

   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub
        try {
            db.execSQL("drop table if exists "+mTableName);
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

8、ConcurrentHashMap是個什麼?

    ConcurrentHashMap的在併發情況下使用的HashMap。普通的HashMap在併發情況下使用put方法會容易引起死循環。關於併發如下:http://ifeve.com/concurrenthashmap/

9、Date的日期如何比較?

    Date的日期比較:date1.after(date2)表示的是如果date1在date2之後就返回true,比如date1=2015-01-23,date2=2014-12-25,結果返回true,此時如果是date1.before(date2)將會返回false.此外,講一個字符串的時間轉換爲Date直接用new SimpleDateFormat("....").parse("...");都是些無關痛癢的小問題,不過還是習慣記錄下。

10、如何解決ScrollVIew和ListView的衝突?

    /**  
     * 重新計算ListView的高度,解決ScrollView和ListView兩個View都有滾動的效果,在嵌套使用時起衝突的問題  
     * @param listView  
     */  
    public void setListViewHeight(ListView listView) {    
            
        // 獲取ListView對應的Adapter    
        
        ListAdapter listAdapter = listView.getAdapter();    
        
        if (listAdapter == null) {    
            return;    
        }    
        int totalHeight = 0;    
        for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回數據項的數目    
            View listItem = listAdapter.getView(i, null, listView);    
            listItem.measure(0, 0); // 計算子項View 的寬高    
            totalHeight += listItem.getMeasuredHeight(); // 統計所有子項的總高度    
        }    
        
        ViewGroup.LayoutParams params = listView.getLayoutParams();    
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));    
        listView.setLayoutParams(params);    
    }

    ScrollView只能有一個子View。需要注意的是子ListView的每個Item必須是LinearLayout,不能是其他的,因爲其他的Layout(如RelativeLayout)沒有重寫onMeasure(),所以會在onMeasure()時拋出異常。原文在此http://blog.csdn.net/wulianghuan/article/details/8627958。其實也可以重寫一個ListView,只需要重寫其onMeasure()方法。


11、Eclipse非正常性錯誤。

    從我電腦上拷了Android項目到公司電腦上的Eclipse的workeplace,出現overlaps the location of another project: 'XXX'錯誤,項目重複了。貌似是Eclipse在導入創建項目的時候會創建同名的目錄,因此會報錯,我把項目放在非workplace目錄可以正常導入,但是我的項目引用了workplace中的其他項目!導致項目雖然能夠正常導入但是不能正常使用,因此我在workplace中再建一個目錄用於放我導入的項目,這一次就ok了!

12、EditText如何在代碼中設置成密碼形式?

    使用代碼將EditText設置爲密碼形式:inputEt.setTransformationMethod(PasswordTransformationMethod.getInstance());

13.獲取手機屏幕分辨率(高和寬)的方法?:

public static float[] getWHofDevice(Activity ac){
		 float[] wh = new float[2];
		 //Display用於展示尺寸和密度的類
		 Display display = ac.getWindowManager().getDefaultDisplay(); 
		 //Point類封裝了座標系的X軸和Y軸兩個座標點
		 Point size = new Point();
		 display.getSize(size);
		 wh[0] = size.y;
		 wh[1] = size.x;
		 return wh;
	 }

    當然了,也可以用一下方法:

        Display diaplay = getWindowManager().getDefaultDisplay();
        Point point = new Point();
        diaplay.getSize(point);
        int x = point.x;
        int y = point.y;

14、MotionEvent的getRowX()和getX()的區別?

    MotionEvent的getRowX()表示獲取的是滑動的相對屏幕的X軸座標,getX()表示相對於被滑動的View的座標,getX()的值不會超過該VIew的寬,getY()和getRowY()同理。

15、ListView的Item設置Selector不起作用?

    在ListView的Item的控件上設置Selector必須對該控件設置一個clickable屬性爲true纔有效,否則設置會不起作用。

16、自定義視圖重寫onMeasure()不調用setMeasureDimension()?

    自定義視圖中,當重寫onMeasure()方法時,如果不super.onMeasure(),那麼就必須設置setMeasuredDimension(width, height);的值。

17、View的post()和Handler的post()區別?

    關於View的post()方法和Handler的post()、sendMessage(..)的方法的比較,實際上View的post()方法都是調用了Handler的post()或postDelay()方法,而Handler的post()方法最終還是調用它自己的sendMessageAtTime()方法。

18、沒事就看看別人項目源碼唄:

    http://blog.csdn.net/shimiso/article/details/14522093

19、AndroidStudio啓動報IllegalArgumentException錯誤?錯:java.lang.RuntimeException: java.lang.IllegalArgumentException: Argument for @NotNull parameter 'name' of com/android/tools/idea/welcome/Platform.<init> must not be null,在網上搜到的解決方案:

    1)進入剛安裝的Android Studio目錄下的bin目錄。找到idea.properties文件,用文本編輯器打開。
    2)在idea.properties文件末尾添加一行: disable.android.first.run=true ,然後保存文件。
    3)關閉Android Studio後重新啓動,便可進入界面。、

20、.在做適配的時候報錯Resources$NotFoundException

    在做適配的時候報錯:android.content.res.Resources$NotFoundException: File res/drawable-hdpi/expanded.PNG from drawable resource ID #0x7f02007d: .xml extension required。已經解決,http://www.360doc.com/content/12/1205/14/1801810_252271083.shtml

21、Adapter的getView()方法的position總是返回0?

    Adapter的getView()方法的position總是返回0,明明有很多item,但是返回的總是0,原因是這些item中的高度是不同的,在變化,這導致ListView重繪了。

22、如何擺脫使用findViewById的困擾?

      1創建一個基類,BaseActivity並繼承Activity

      方法如下:

public class BaseActivity extends Activity {

  @Override

  protected void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

  }

  protected <T extends View> T generateFindViewById(int id) {

      //return返回view時,加上泛型T

      return (T) findViewById(id);

  }

}

      2自己寫的Activity都去繼承BaseActivity

之後我們自己寫的每一個Activity都去繼承BaseActivity,然後在初始化控件時直接使用generateFindViewById來代替findViewById即可。

23、如何更方便的在子線程創建Looper

    有時候我們需要在子線程中創建Handler對象,我們知道,在線程中創建Handler的時候必須保證當前線程有Looper對象,因此通常需要在run方法中調用prepare()和loop,其實有一種更方便的用法來創建Loop,那就是使用HandlerThread實現,HandlerThrtead是SDK提供的一個簡單的類,用法如下:

    (1)創建HandlerThread對象:HandlerThread handlerThread = new HandlerThread("my_handler");

    (2)調用start方法:handlerThread.start();

    (3)創建Handler:Handler handler = new Handler(handlerThread.getLooper());如此即可。

24、如何監聽文件/目錄的變化

    有時候我們需要監聽手機上指定的目錄或文件的變化,如被刪除、被修改或新增了文件等,這種變化需要我們的app隨時知道,應該怎麼實現呢?SDK提供了一個FileObserver類給我們,可以很容易的實現:

   (1)繼承FileObserver類實現其抽象方法來完成自己的FileObserver。

   (2)爲指定目錄/文件添加監聽:添加監聽其實就是在創建FileObserver對象的時候傳遞路徑:

				FileObserver mFrameworkInstallObserver = new AppDirObserver(
						mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
    其中的mFrameworkDir.getPath()就是監聽system/app目錄。

   (3)啓動監聽:mFrameworkInstallObserver.startWatching();

25、Android如何緩存數據

    可以使用Android自帶的LruCache或者使用輕量級的ACache(網上搜).

26、ImageView在佈局文件會出現空白的問題

    在佈局文件的ImageView標籤中加入android:adjustViewBounds="true"或者在代碼中設置ImageView.setAdjustViewBounds(true)即可。

27、關於TextView的一些屬性用法

     首先需要繼承TextView,什麼也不用幹,就把isFocused()返回true即可。

   (1)限制文本長度:android:maxEms="6",最長只能顯示6個字符。

   (2)跑馬燈x效果:android:singleLine="true",android:ellipsize="marquee"

   (3)當然我們也可以在代碼中設置:tv.setEllipsize(TruncateAt.MARQUEE);

28、關於EditText的一些屬性用法

   (1)設置多行顯示,類似html的textarea:android:lines="4",顯示四行,

   (2)如果lines是多行,光標顯示在第一行: android:lines="4",android:gravity="top",這樣就行了。

29、什麼時候用關鍵字static來修飾屬性、方法?

    “你的屬性或方法是否需要在沒有對象的情況下使用?如果是那麼就該用static了,如果不是那麼就別用static了。”。

30、LIstView單擊item無響應的問題

    主要是焦點問題,這裏就需要用到android:descendantFocusability屬性了,詳見此博客http://www.cnblogs.com/eyu8874521/archive/2012/10/17/2727882.html ;   。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章