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的好。