1. 程式人生 > >【Android開發經驗】LayoutInflater——80%的Android程式設計師對它並不瞭解甚至錯誤使用

【Android開發經驗】LayoutInflater——80%的Android程式設計師對它並不瞭解甚至錯誤使用

這個標題起的有點誇張哈,但是LayoutInflater這個類的一些用法,在Android開發者使用的過程中,確實存在著一些很普遍的誤區,最起碼我研究的這麼多小專案的原始碼,基本上都在錯誤的使用這個類。今天,看到了一篇文章講LayoutInflater的用法,瞬間感覺自己對這個類確實不夠了解,於是簡單的看了下LayoutInflater類的原始碼,對這個類有了新的認識。

首先,LayoutInflater這個類是用來幹嘛的呢?

我們最常用的便是LayoutInflater的inflate方法,這個方法過載了四種呼叫方式,分別為:

1. public View inflate(int resource, ViewGroup root)

2. public View inflate(int resource, ViewGroup root, boolean attachToRoot)

3.public View inflate(XmlPullParser parser, ViewGroup root)

4.public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)

這四種使用方式中,我們最常用的是第一種方式,inflate方法的主要作用就是將xml轉換成一個View物件,用於動態的建立佈局。雖然過載了四個方法,但是這四種方法最終呼叫的,還是第四種方式。第四種方式也很好理解,內部實現原理就是利用Pull解析器,對Xml檔案進行解析,然後返回View物件。

我們以我們經常使用的第一種形式為例,你在重寫BaseAdapter的getView方法的時候是否這樣做過

[java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. public View getView(int position, View convertView, ViewGroup parent) { 
  2.     if (convertView == null) { 
  3.         convertView = inflate(R.layout.item_row, null); 
  4.     } 
  5.     return convertView; 
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = inflate(R.layout.item_row, null);
    }
    return convertView;
}
inflate方法有三個引數,分別是

1.resource佈局的資源id

2.root填充的根檢視

3.attachToRoot是否將載入的檢視繫結到根檢視中

在這個例子中,我們將root引數設為空,功能確實實現了,但是這裡還隱藏著一個隱患,這種方式並不是inflate正確的使用姿勢,下面我們通過一個Demo,來說一下這樣使用造成的弊端。

首先,我們建立一個這樣的專案


這裡三個介面,一個主介面,兩個測試介面,佈局檔案中,主介面只負責介面跳轉,兩個測試介面都是一個簡單的Listview,item佈局顯示效果如下


對應的佈局檔案如下

[html] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="60dp"
  5.     android:background="@android:color/holo_orange_light"
  6.     android:gravity="center"
  7.     android:orientation="vertical">
  8.     <TextView
  9.         android:id="@+id/tv"
  10.         android:layout_width="wrap_content"
  11.         android:layout_height="wrap_content"
  12.         android:text="11"
  13.         android:textColor="@android:color/black"
  14.         android:textSize="22sp"/>
  15. </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="@android:color/holo_orange_light"
    android:gravity="center"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="11"
        android:textColor="@android:color/black"
        android:textSize="22sp" />

</LinearLayout>

OneActivity的程式碼如下 [java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicclass OneActivity extends Activity { 
  2.     private ListView list1; 
  3.     @Override
  4.     protectedvoid onCreate(Bundle savedInstanceState) { 
  5.         super.onCreate(savedInstanceState); 
  6.         setContentView(R.layout.activity_one); 
  7.         list1 = (ListView) findViewById(R.id.list1); 
  8.         list1.setAdapter(new MyAdapter(this)); 
  9.     } 
  10.     privateclass MyAdapter extends BaseAdapter { 
  11.         private LayoutInflater inflater; 
  12.         MyAdapter(Context context) { 
  13.             inflater = LayoutInflater.from(context); 
  14.         } 
  15.         @Override
  16.         publicint getCount() { 
  17.             return 20
  18.         } 
  19.         @Override
  20.         public Object getItem(int position) { 
  21.             return position; 
  22.         } 
  23.         @Override
  24.         publiclong getItemId(int position) { 
  25.             return position; 
  26.         } 
  27.         @Override
  28.         public View getView(int position, View convertView, ViewGroup parent) { 
  29.             if (convertView == null) { 
  30.                 convertView = inflater.inflate(R.layout.item_list, null); 
  31.             } 
  32.             TextView tv = (TextView) convertView.findViewById(R.id.tv); 
  33.             tv.setText(position+""); 
  34.             return convertView; 
  35.         } 
  36.     } 
public class OneActivity extends Activity {

	private ListView list1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_one);
		list1 = (ListView) findViewById(R.id.list1);
		list1.setAdapter(new MyAdapter(this));
	}

	private class MyAdapter extends BaseAdapter {

		private LayoutInflater inflater;

		MyAdapter(Context context) {
			inflater = LayoutInflater.from(context);
		}

		@Override
		public int getCount() {
			return 20;
		}

		@Override
		public Object getItem(int position) {
			return position;
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {

			if (convertView == null) {
				convertView = inflater.inflate(R.layout.item_list, null);
			}
			TextView tv = (TextView) convertView.findViewById(R.id.tv);
			tv.setText(position+"");
			return convertView;
		}

	}

}

TwoActivity的程式碼如下 [java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicclass TwoActivity extends Activity { 
  2.     private ListView list2; 
  3.     @Override
  4.     protectedvoid onCreate(Bundle savedInstanceState) { 
  5.         super.onCreate(savedInstanceState); 
  6.         setContentView(R.layout.activity_two); 
  7.         list2 = (ListView) findViewById(R.id.list2); 
  8.         list2.setAdapter(new MyAdapter(this)); 
  9.     } 
  10.     privateclass MyAdapter extends BaseAdapter { 
  11.         private LayoutInflater inflater; 
  12.         MyAdapter(Context context) { 
  13.             inflater = LayoutInflater.from(context); 
  14.         } 
  15.         @Override
  16.         publicint getCount() { 
  17.             return20
  18.         } 
  19.         @Override
  20.         public Object getItem(int position) { 
  21.             return position; 
  22.         } 
  23.         @Override
  24.         publiclong getItemId(int position) { 
  25.             return position; 
  26.         } 
  27.         @Override
  28.         public View getView(int position, View convertView, ViewGroup parent) { 
  29.             if (convertView == null) { 
  30.                 convertView = inflater.inflate(R.layout.item_list, parent,false); 
  31.             } 
  32.             TextView tv = (TextView) convertView.findViewById(R.id.tv); 
  33.             tv.setText(position + ""); 
  34.             return convertView; 
  35.         } 
  36.     } 
public class TwoActivity extends Activity {
	private ListView list2;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_two);
		list2 = (ListView) findViewById(R.id.list2);
		list2.setAdapter(new MyAdapter(this));
	}

	private class MyAdapter extends BaseAdapter {

		private LayoutInflater inflater;

		MyAdapter(Context context) {
			inflater = LayoutInflater.from(context);
		}

		@Override
		public int getCount() {
			return 20;
		}

		@Override
		public Object getItem(int position) {
			return position;
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {

			if (convertView == null) {
				convertView = inflater.inflate(R.layout.item_list, parent,false);
			}
			TextView tv = (TextView) convertView.findViewById(R.id.tv);
			tv.setText(position + "");
			return convertView;
		}

	}

}

兩個檔案最關鍵的區別就一句話,

在getView方法中,OneActivity是

convertView = inflater.inflate(R.layout.item_list, null);

在getView方法中,TwoActivity是

convertView = inflater.inflate(R.layout.item_list, parent,false);

我們先看一下顯示效果,再說兩者的區別

OneActivity效果


TwoActivity的顯示效果


我們可以很明顯的看出來,使用第一種方式,根佈局的高度設定60dp沒有起作用,系統還是按照包裹內容的方式載入的,為什麼會產生這種效果呢?我們從需要inflate方法的原始碼中找一下答案。

首先,方式一的原始碼實現

[java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. public View inflate(XmlPullParser parser, ViewGroup root) { 
  2.         return inflate(parser, root, root != null); 
  3.     } 
public View inflate(XmlPullParser parser, ViewGroup root) {
        return inflate(parser, root, root != null);
    }

當我們使用方式一,並且第二個引數傳入null的時候,預設呼叫的是下面的方法,並且attachToRoot是false [java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. public View inflate(int resource, ViewGroup root, boolean attachToRoot) { 
  2.         if (DEBUG) System.out.println("INFLATING from resource: " + resource); 
  3.         XmlResourceParser parser = getContext().getResources().getLayout(resource); 
  4.         try
  5.             return inflate(parser, root, attachToRoot); 
  6.         } finally
  7.             parser.close(); 
  8.         } 
  9.     } 
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
        if (DEBUG) System.out.println("INFLATING from resource: " + resource);
        XmlResourceParser parser = getContext().getResources().getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }

在這一個方法中,pull解析器將資源id轉化成XmlResourceParser物件,又傳給了第四種方式,所以我們需要重點看的還是第四種方式是如何實現的 [java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { 
  2.         synchronized (mConstructorArgs) { 
  3.             Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate"); 
  4.             final AttributeSet attrs = Xml.asAttributeSet(parser); 
  5.             Context lastContext = (Context)mConstructorArgs[0]; 
  6.             mConstructorArgs[0] = mContext; 
  7.             View result = root; 
  8.             try
  9.                 // Look for the root node.
  10.                 int type; 
  11.                 while ((type = parser.next()) != XmlPullParser.START_TAG && 
  12.                         type != XmlPullParser.END_DOCUMENT) { 
  13.                     // Empty
  14.                 } 
  15.                 if (type != XmlPullParser.START_TAG) { 
  16.                     thrownew InflateException(parser.getPositionDescription() 
  17.                             + ": No start tag found!"); 
  18.                 } 
  19.                 final String name = parser.getName(); 
  20.                 if (DEBUG) { 
  21.                     System.out.println("**************************"); 
  22.                     System.out.println("Creating root view: "
  23.                             + name); 
  24.                     System.out.println("**************************"); 
  25.                 } 
  26.                 if (TAG_MERGE.equals(name)) { 
  27.                     if (root == null || !attachToRoot) { 
  28.                         throw new InflateException("<merge /> can be used only with a valid "
  29.                                 + "ViewGroup root and attachToRoot=true"); 
  30.                     } 
  31.                     rInflate(parser, root, attrs, false); 
  32.                 } else
  33.                     // Temp is the root view that was found in the xml
  34.                     View temp; 
  35.                     if (TAG_1995.equals(name)) { 
  36.                         temp = new BlinkLayout(mContext, attrs); 
  37.                     } else
  38.                         temp = createViewFromTag(root, name, attrs); 
  39.                     } 
  40.                     ViewGroup.LayoutParams params = null
  41.                     if (root != null) { 
  42.                         if (DEBUG) { 
  43.                             System.out.println("Creating params from root: "
  44.                                     root); 
  45.                         } 
  46.                         // Create layout params that match root, if supplied
  47.                         params = root.generateLayoutParams(attrs); 
  48.                         if (!attachToRoot) { 
  49.                             // Set the layout params for temp if we are not
  50.                             // attaching. (If we are, we use addView, below)
  51.                             temp.setLayoutParams(params); 
  52.                         } 
  53.                     } 
  54.                     if (DEBUG) { 
  55.                         System.out.println("-----> start inflating children"); 
  56.                     } 
  57.                     // Inflate all children under temp
  58.                     rInflate(parser, temp, attrs, true); 
  59.                     if (DEBUG) { 
  60.                         System.out.println("-----> done inflating children"); 
  61.                     } 
  62.                     // We are supposed to attach all the views we found (int temp)
  63.                     // to root. Do that now.
  64.                     if (root != null && attachToRoot) { 
  65.                         root.addView(temp, params); 
  66.                     } 
  67.                     // Decide whether to return the root that was passed in or the
  68.                     // top view found in xml.
  69.                     if (root == null || !attachToRoot) { 
  70.                         result = temp; 
  71.                     } 
  72.                 } 
  73.             } catch (XmlPullParserException e) { 
  74.                 InflateException ex = new InflateException(e.getMessage()); 
  75.                 ex.initCause(e); 
  76.                 throw ex; 
  77.             } catch (IOException e) { 
  78.                 InflateException ex = new InflateException( 
  79.                         parser.getPositionDescription() 
  80.                         + ": " + e.getMessage()); 
  81.                 ex.initCause(e); 
  82.                 throw ex; 
  83.             } finally
  84.                 // Don't retain static reference on context.
  85.                 mConstructorArgs[0] = lastContext; 
  86.                 mConstructorArgs[1] = null
  87.             } 
  88.             Trace.traceEnd(Trace.TRACE_TAG_VIEW); 
  89.             return result; 
  90.         } 
  91.     } 
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
        synchronized (mConstructorArgs) {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");

            final AttributeSet attrs = Xml.asAttributeSet(parser);
            Context lastContext = (Context)mConstructorArgs[0];
            mConstructorArgs[0] = mContext;
            View result = root;

            try {
                // Look for the root node.
                int type;
                while ((type = parser.next()) != XmlPullParser.START_TAG &&
                        type != XmlPullParser.END_DOCUMENT) {
                    // Empty
                }

                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(parser.getPositionDescription()
                            + ": No start tag found!");
                }

                final String name = parser.getName();
                
                if (DEBUG) {
                    System.out.println("**************************");
                    System.out.println("Creating root view: "
                            + name);
                    System.out.println("**************************");
                }

                if (TAG_MERGE.equals(name)) {
                    if (root == null || !attachToRoot) {
                        throw new InflateException("<merge /> can be used only with a valid "
                                + "ViewGroup root and attachToRoot=true");
                    }

                    rInflate(parser, root, attrs, false);
                } else {
                    // Temp is the root view that was found in the xml
                    View temp;
                    if (TAG_1995.equals(name)) {
                        temp = new BlinkLayout(mContext, attrs);
                    } else {
                        temp = createViewFromTag(root, name, attrs);
                    }

                    ViewGroup.LayoutParams params = null;

                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            temp.setLayoutParams(params);
                        }
                    }

                    if (DEBUG) {
                        System.out.println("-----> start inflating children");
                    }
                    // Inflate all children under temp
                    rInflate(parser, temp, attrs, true);
                    if (DEBUG) {
                        System.out.println("-----> done inflating children");
                    }

                    // We are supposed to attach all the views we found (int temp)
                    // to root. Do that now.
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }

                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }
                }

            } catch (XmlPullParserException e) {
                InflateException ex = new InflateException(e.getMessage());
                ex.initCause(e);
                throw ex;
            } catch (IOException e) {
                InflateException ex = new InflateException(
                        parser.getPositionDescription()
                        + ": " + e.getMessage());
                ex.initCause(e);
                throw ex;
            } finally {
                // Don't retain static reference on context.
                mConstructorArgs[0] = lastContext;
                mConstructorArgs[1] = null;
            }

            Trace.traceEnd(Trace.TRACE_TAG_VIEW);

            return result;
        }
    }

程式碼比較長,我們重點關注下面的程式碼 [java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. if (root != null) { 
  2.                         if (DEBUG) { 
  3.                             System.out.println("Creating params from root: "
  4.                                     root); 
  5.                         } 
  6.                         // Create layout params that match root, if supplied
  7.                         params = root.generateLayoutParams(attrs); 
  8.                         if (!attachToRoot) { 
  9.                             // Set the layout params for temp if we are not
  10.                             // attaching. (If we are, we use addView, below)
  11.                             temp.setLayoutParams(params); 
  12.                         } 
  13.                     } 
if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            temp.setLayoutParams(params);
                        }
                    }

這些程式碼的意思就是,當我們傳進來的root引數不是空的時候,並且attachToRoot是false的時候,也就是上面的TwoActivity的實現方式的時候,會給temp設定一個LayoutParams引數。那麼這個temp又是幹嘛的呢? [java] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. <pre name="code"class="java">// We are supposed to attach all the views we found (int temp)
  2.                     // to root. Do that now.
  3.                     if (root != null && attachToRoot) { 
  4.                         root.addView(temp, params); 
  5.                     } 
  6.                     // Decide whether to return the root that was passed in or the
  7.                     // top view found in xml.
  8.                     if (root == null || !attachToRoot) { 
  9.                         result = temp; 
  10.                     } 
<pre name="code" class="java">// We are supposed to attach all the views we found (int temp)
                    // to root. Do that now.
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }

                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }



現在應該明白了吧,當我們傳進來的root不是null,並且第三個引數是false的時候,這個temp就被加入到了root中,並且把root當作最終的返回值返回了。而當我們設定root為空的時候,沒有設定LayoutParams引數的temp物件,作為返回值返回了。

因此,我們可以得出下面的結論:

1.若我們採用convertView = inflater.inflate(R.layout.item_list, null);方式填充檢視,item佈局中的根檢視的layout_XX屬性會被忽略掉,然後設定成預設的包裹內容方式

2.如果我們想保證item的檢視中的引數不被改變,我們需要使用convertView = inflater.inflate(R.layout.item_list, parent,false);這種方式進行檢視的填充

3.除了使用這種方式,我們還可以設定item佈局的根檢視為包裹內容,然後設定內部控制元件的高度等屬性,這樣就不會修改顯示方式了。

最後,給出那篇文章的連結http://blog.jobbole.com/72156/大家可以去看看

相關推薦

Android開發經驗LayoutInflater——80%的Android程式設計師並不瞭解甚至錯誤使用

這個標題起的有點誇張哈,但是LayoutInflater這個類的一些用法,在Android開發者使用的過程中,確實存在著一些很普遍的誤區,最起碼我研究的這麼多小專案的原始碼,基本上都在錯誤的使用這個類。今天,看到了一篇文章講LayoutInflater的用法,瞬間感覺自己對

Android開發經驗android:windowSoftInputMode屬性具體解釋

中一 mtk wid water ren 而是 orien 表示 不能 本文章來自CSDN博客:http://blog.csdn.net/zhaokaiqiang1992。轉載請註明地址! 在前面的一篇文章中,簡單的介紹了一下怎樣實現軟鍵盤不自己主動彈出,使

Android開發經驗APP的快取檔案到底應該存在哪?看完這篇文章你應該就自己清楚了

只要是需要進行聯網獲取資料的APP,那麼不管是版本更新,還是圖片快取,都會在本地產生快取檔案。那麼,這些快取檔案到底放在什地方合適呢?系統有沒有給我們提供建議的快取位置呢?不同的快取位置有什麼不同呢?今天這篇文章就是主要來說明這個問題的。     首先,我們要知道,在A

Android開發經驗設定使用者頭像並裁剪,僅僅是這麼簡單?

    在做APP的時候,如果有使用者系統功能,那麼一般都逃不了這個需求,就是給使用者設定頭像,而設定頭像,又包括從拍照和從相簿選取兩個方式,而且選擇了之後,一般又都會要求對影象進行裁剪,讓使用者設定頭像。今天這篇文章就是介紹如何完成這個需求的。    我們首先分析一下需求。

Android開發經驗關於“多執行緒斷點續傳下載”功能的一個簡單實現和講解

    上班第一天,在技術群裡面和大家閒扯,無意中談到了關於框架的使用,一個同學說為了用xUtils的斷線續傳下載功能,把整個庫引入到了專案中,在google的官方建議中,是非常不建議這種做法的,集合框架雖然把很多功能整合起來,但是程式碼越多,出現問題的可能越大,而且無形之中

劍指offer陣列中的逆序(校正書上錯誤歸併排序

題目描述 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007 題目保證輸入的陣列中沒有的相同的數字 資料範圍:

分享8年開發經驗,淺談java程式設計師職業規劃

在中國有很多人都認為IT行為是吃青春飯的,如果過了30歲就很難有機會再發展下去!其實現實並不是這樣子的,在下從事.NET及JAVA方面的開發的也有8年的時間了,在這裡在下想憑藉自己的親身經歷,與大家一起探討一下。 明確入行的目的 很多人幹IT這一行都衝著“收入高”這一點的,

Android開發-5界面裝修,五大布局你選誰

比例 技術分享 article 嵌套 content java lin layout mark 前言:假設要開一家店,門店裝修是非常重要的事情。有錢都請專門的建築設計公司來設計裝修,沒錢的僅僅能自己瞎折騰。好不好看全憑自己的感覺。像Android開發。在移動端大家看到的

android開發筆記如何讓ImageButton去掉白色邊框和讓ImageButton具有點選效果

這是我從網上學來的,怕忘記,遂記起來 如何讓ImageButton去掉白色邊框 android:background="#00000000" //把背景變透明放在那一段程式碼裡呢?放在layout裡面的.xml檔案裡 如: <ImageButton a

Linux/Android開發記錄學習、記錄、分享Linux/Android開發技術

專欄達人 授予成功建立個人部落格專欄

Android開發日記Popupwindow 完美demo

Popupwindow 完美demo實現 圖示:                                                                                                       關鍵程式碼說明:

Android 開發入門android studio 控制檯列印輸出日誌

有些情況下,不方便使用斷點的方式來除錯,而是希望在控制檯列印輸出日誌,使用過Eclipse的同學都知道Java可以使用 System.out.println(""); 來在控制檯列印輸出日誌,但是在android studio中卻是不行的,還是有差別的,那應該用什麼呢?and

Android開發bugDropping event due to no window focus

問題描述: 使用android自帶視訊播放器播放視訊,按返回鍵不能退出這個介面(Android_4.4.4系統); Log如下: 11-25 16:37:31.498: W/ViewRootImpl(27708): Dropping event due to no win

Android 開發入門使用Android模擬器預覽除錯程式

在上篇“走進Android開發的世界,HelloWorld”,我們建立了一個Android 專案 HelloWorld,並演示瞭如何通過USB連線手機檢視執行效果;而如果沒有手機或沒有對應型號的手機,又

Android 開發入門我為什麼要在Android找工作越來越難的時候開始學習

首先,Android是不是真的找工作越來越難呢?這個可能是大家最關心的。這個受大的經濟環境以及行業發展前景的影響,同時也和個人因素有關。2016-08-26近期一方面是所在的公司招聘Java開發人員很難招到合適的,投簡歷的人很少;而另一方面,經常聽身邊的人說Android、i

Android開發技巧Fragment中獲取Context物件的兩種方法

我們在使用Fragment的時候經常需要傳遞Context型別的引數,【Android用的比較多的就是下面幾個導航按鈕,點選切換fragment(之前Android studio2.0以前是可以new fragment(context)時傳遞Context,但後來升級了studio2.1.2之後,new

Android 開發教程使用Intent傳送簡訊

本章節翻譯自《Beginning-Android-4-Application-Development》,如有翻譯不當的地方,敬請指出。使用SmsManager類,可以在自己編寫的程式內部發送簡訊,而不需要呼叫系統的簡訊應用。然而,有的時候呼叫系統內建的簡訊應用會更加方便。這時

android實戰經驗關閉Fragment的方法

getActivity().onBackPressed()。 該方法用於監聽使用者點選返回鍵的事件,也可以呼叫它來關閉view。 在FragmentTransaction物件中新增fragment

商城開發Android 仿淘寶商品詳情頁下拉足跡修改版

開發商城的快有半個月了,需要做到詳情頁下拉足跡的效果,網上找了找沒找到,找到一個差不多還有點問題,然後在基礎上進行了二次開發 感謝http://blog.csdn.net/yaphetzhao/article/details/53736471  YaphetZhao的部落格

Android 開發入門Android裝置監視器之除錯工具DDMS使用初探

Android Studio提供了一個很實用的工具Android裝置監視器(Android device monitor),該監視器中最常用的一個工具就是DDMS(Dalvik Debug Monitor Service),是 Android 開發環境中的Dalvik虛擬機器