2012.11.10 10:30
想要學習android開發已經有很長的時間了,別人的源碼也看了很多,但只是看覺得我也行,今天實際動手就菜得一B,連新建一個hello-world,運行都會報錯。
把自己各種錯誤記錄在這裏,方便溫故而知新。
什麼是AndroidManifest.xml?
應該感謝英語老師,就跟自己寫程序喜歡用拼音命名變量一樣,老外也喜歡用英語。AndroidManifest確實就像一個貨單,把所有要用到的東西都列了出來。
理解我的第一張manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jincheng.talk"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<!-- declare permission -->
<!-- allow phone to vibrate -->
<uses-permission android:name="android.permission.VIBRATE"/>
<!-- allow shortcut icon -->
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<application
android:name=".myApp"
android:icon="@drawable/geotalkico"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>service,
</manifest>
提請我注意,android:icon後面確實是一張圖表的路徑,android:label後面也確實是一個label的內容,但是android:name並不只是一個像id一樣的東西,對於application,activity,service來說都對應着一個具體的java類。
比如在這裏,我的src下面只有com.jincheng.talk.MainActivity.java而沒有.myApp,在run的時候就報錯了
Unable to instantiate application com.jincheng.talk.myApp: java.lang.ClassNotFoundException
這應該就是沒有看書學習的後果了,看來需要去買本書看看- -
在此,通過android:name指定類的方法有三種,
一種就是通常在用的.MainActivity,只寫類名,包名則用上面綠色字體聲明,在這裏如果實在想省略"."也是可以的;
第二種當然就是指定全名;
第三種則是指定相對類名,.talk.MainActivity,包名在上面聲明瞭。在這裏如果想省略"."就不行了。
這個感覺跟flex裏面聲明mx好像- -
這是我犯的第一個2B錯誤,記錄下來。
這個標紅標綠的感覺好囧- -我怎麼就忘了這本來就是html了呢- -
manifest中的activity
現在我有了第一個activity MainActivity,雖然是系統生成的。在run的時候,系統順利通過Application,找到了這個activity,然後通過android:name順藤摸瓜,找到了MainActivity.javapackage com.jincheng.talk;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v("jout", "begin");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
感謝系統,讓我不至於連第一行代碼都寫不出來。
看見onCreate是一件很開心的事情,有create自然會有start也應該會有stoped或者exited或者destroyed,一個實例從出生到死亡。
感謝google感謝飛雪無情,他在http://flysnow.iteye.com/blog/813490中詳細介紹了activity的生命週期。
根據飛雪無情測試的結果一個Activity在啓動的時候會執行onCreate()->onStart()->onResume(),在結束(或離開)的時候會執行onPause()->onStop()->onDestroy(),這是一個容易理解的過程。
那麼這些過程具體是在神馬時候產生的呢?setContentView又是在神馬時候起作用的?onCreateOptionsMenu又是神馬?
肚子好餓,吃過飯回來再研究- -順便買本書- -
2012.11.12 8:50
activity的生命週期
在MainActivity類中添加各個生命週期,觀察神馬時候觸發
package com.jincheng.talk;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
private final static String TAG="joutMainActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG, "begin");
}
@Override
protected void onStart() {
super.onStart();
Log.v(TAG, "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.v(TAG, "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.v(TAG, "onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.v(TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.v(TAG, "onDestroy");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
運行程序,發現logcat中顯示begin->onstart->onresume
首先這些事件不需要在代碼中觸發,android會按需觸發 ,
如果我們選擇返回桌面,那麼會觸發onpause->onstop
當onpause時activity不可見,onstop時則暫停onpause
activity通過setContentView操作layout佈局,如果只是通過setContentView切換佈局,而不調用新的activity,舊有的activity並不會重新觸發生命週期。
我們新建一個佈局,並在MainActivity的onstart方法中添加
setContentView(R.layout.activity_main2);
運行程序,觸發順序依然是begin->onstart->onresume一個都不能少
我剛知道了單個activity中的生命週期是腫麼回事,如果我在mainactivity中調用了別的activity又會腫麼樣呢?於是我copy了mainactivity並新建了mainactivity2,並在activity_main佈局文件中添加了一個button,同時在mainactivity類中給了這個button一個click事件
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG, "begin");
Button btnSubmit=(Button) findViewById(R.id.submitmain);
btnSubmit.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
startActivity(new Intent(MainActivity.this, MainActivity2.class));
//finish();//關閉當前Activity
}
});
}
通過startActivity方法調用了MainActivity2
同樣的activity_main2中也有了一個button,用於退出
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG, "begin");
Button btnSubmit=(Button) findViewById(R.id.submitmain);
btnSubmit.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
finish();//關閉當前Activity
}
});
}
運行……單擊submit1,報錯……
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.jincheng.talk/com.jincheng.talk.MainActivity2}; have you declared this activity in your AndroidManifest.xml?
因爲MainActivity2沒有在AndroidManifest.xml中聲明,所以系統不認識他。
OK,在AndroidManifest.xml中聲明一下,
<activity
android:name=".MainActivity2"
android:label="@string/title_activity_main">
</activity>
再運行就OK了,
那麼調用情況是腫麼樣的呢?
首先是MainActivity onPause,隨後MainActivity2 begin->onstart->onresume,最後MainActivity OnStop,
此時我們再點擊submit2,
首先是MainActivity2 onPause,隨後MainActivity onstart->onresume,MainActivity2 OnStop,
因爲submit2的onclick事件中有使用finish(),所以最後MainActivity2 OnDestroy。
如果在MainActivity的onclick事件中也使用finish(),那麼MainActivity 在OnStop後就會OnDestroy,
此時單擊submit2就會直接退出程序,回到桌面,application就結束了。
所以如果只是從主頁面調用旁的頁面,還是不要finish的好。