Android学习笔记四之Activity

Android四大组件之Activity

1、什么是Activity

  Activity是Android四大组件之一,用于显示View。Activity是一个应用程序组件,提供一个用户交互的接口,其本身是没有界面的,Activity类创建一个窗口,在上面可以绘制用户接口。窗口通常充满屏幕,也可以小于屏幕而悬浮于其他窗口之上。

  开发者可以通过Activity类提供的setContentView(View)接口将View放到Activity创建的窗口上。一个程序一般由多个Activity组成,他们通常是松耦合关系。一个Activity可以启动另外一个Activity。每次一个Activity启动,前一个Activity就停止,但是Android系统会保留Activity在一个栈上,当用户完成当前Activity然后点击back按钮时,它就会被弹出栈并被销毁。所有的Activity类必须在AndroidManifest.xml文件中注册,不注册会报错。例如:

    <activity android:name=".BaseActivity" />
    <activity android:name=".activity.AboutCSDNActivity" />
    <activity android:name=".activity.BlogOsphereActivity" />
    <activity android:name=".activity.FeedBackActivity" />
    <activity android:name=".activity.WebActivity" />
    <activity android:name=".activity.AllBloggerActivity" />
    <activity android:name=".activity.BlogDetailActivity" />

2、activity的生命周期方法

下图是Android api中所提供的Activity生命周期图

由图可以看出,Activity有如下生命周期方法,分别是:

  public class Activity extends ApplicationContext {

  protected void onCreate(Bundle savedInstanceState);

  protected void onStart();

  protected void onResume();

  protected void onPause();

  protected void onStop();

  protected void onDestroy();

 }

  一个Activity启动,执行生命周期方法顺序是:onCreate -> onStart -> onResume;当一个Activity被Kill掉时候,执行生命周期方法顺序是:onPause -> onStop -> onDestroy。这是一个完整的生命周期循环。当一个应用正在运行,由于其它应用中断,比如电话来了等,执行的生命周期方法是onPause -> onStop,挂断电话恢复到当前应用,执行的生命周期方法是onStart -> onResume;如果当前应用的Activity是Theme为Translucent(半透明)或者Dialog时,那么中断就是onPause ,恢复的时候onResume。

2.1、各种生命周期方法在系统中的作用

  • onCreate方法:在这里创建界面,可以实现一些界面的初始化工作
  • onStart方法:在onCreate方法之后被调用,或者Activity从stop状态转换为Active状态被调用,可以实现数据的请求
  • onResume方法:在 Activity 从 Pause 状态转换到 Active 状态时被调用。
  • onPause方法:在 Activity 从 Active 状态转换到 Pause 状态时被调用。在这里可以保存一些数据,在onResume方法中可以读取这里保存的数据。
  • onStop方法:在 Activity 从 Active 状态转换到 Stop 状态时被调用。一般我们在这里保存 Activity 的状态信息。
  • onDestroy方法:在 Activity 被结束时调用,它是被结束时调用的最后一个方法,在这里一般做些释放资源,清理内存等工作。

onPause,onstop, onDestroy,三种状态下 activity都有可能被系统kill掉

2.2、Activity的四种状态

Activity有四种状态分别是:

  • Running状态
  • Stopped状态
  • Paused状态
  • Destroyed状态

生命周期方法在各个状态被调用时机如下图:

由上图可以看出:

  • 当Running状态的时候,调用onPause方法可以切换到Pauseed状态。
  • 当在Paused状态的时候,调用onResume方法可以切换到Running状态,调用onStop方法可以切换到Stopped状态,如果应用被退出就切换到Destroyed状态。
  • 当处在Stopped状态时候,调用onRestart方法、onStart方法、onResume方法会切换到Running状态,调用onDestroy方法或者应用被退出就会切换到Destroyed状态。

3、Activity之间的通信

  在 Android 中,不同的 Activity 实例可能运行在一个进程中,也可能运行在不同的进程中。因此我们需要一种特别的机制帮助我们在 Activity 之间传递消息。Android 中通过 Intent 对象来表示一条消息,一个 Intent 对象不仅包含有这个消息的目的地,还可以包含消息的内容,这好比一封 Email,其中不仅应该包含收件地址,还可以包含具体的内容。对于一个 Intent 对象,消息“目的地”是必须的,而内容则是可选项。

  Intent负责对操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。

  在应用中,我们可以通过两种形式来使用Intent:

  直接Intent:指定了component属性的Intent(setClass(Context, Class)来指定)。通过指定具体的组件类,通知应用启动对应的组件。

  间接Intent:没有指定comonent属性的Intent。这些Intent需要包含足够的信息,这样系统才能根据这些信息,在在所有的可用组件中,确定满足此Intent的组件。

对于直接Intent,Android不需要去做解析,因为目标组件已经很明确。

  Android需要解析的是那些间接Intent,通过解析,将 Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。

通过setClass传递消息:

 Intent intent =new Intent(CurrentActivity.this,OtherActivity.class);
 Bundle bundle =new Bundle();
 bundle.putBoolean("boolean_key", true);
 bundle.putString("string_key", "string_value");
 intent.putExtra("key", bundle);
 startActivity(intent);

另一个Activity解析消息:

Intent intent =getIntent();
 Bundle bundle =intent.getBundleExtra("key");
 bundle.getBoolean("boolean_key");
 bundle.getString("string_key");

除了使用intent之外还可以使用sharedpreference传递消息:

 // 写入 SharedPreferences
 SharedPreferences preferences = getSharedPreferences("name", MODE_PRIVATE);
 Editor editor = preferences.edit();
 editor.putBoolean("boolean_key", true);
 editor.putString("string_key", "string_value");
 editor.commit(); 

 // 读取 SharedPreferences
 SharedPreferences preferences = getSharedPreferences("name", MODE_PRIVATE);
 preferences.getBoolean("boolean_key", false);
 preferences.getString("string_key", "default_value");

一个Activity向另外一个Activity传递消息,后一个Activity传回给前一个

例如:A.Activity向B.Activity传递一些消息,当B.Activity关闭的时候回传一些消息给A.Activity

//在A.Activity中加入:

button.setOnClickListener(new OnClickListener(){
   @Override
   public void onClick(View arg0) {
  Intent intent = new Intent();
  intent.setClass(a.this, b.class);
  Bundle bundle = new Bundle();
  bundle.putString("v_id",i_id);
  intent.putExtras(bundle);
  startActivityForResult(intent,0);
  overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
   }

 });

//在B.Activity中加入:
String v_id = this.getIntent().getExtras().getString("v_id");

//在B.Activity 中加入。当关闭b时,传递数据name给a:

   b_close.setOnClickListener(new OnClickListener(){
   @Override
   public void onClick(View arg0) {
   Intent intent = getIntent();
   Bundle bundle = new Bundle();
   bundle.putString("name",name);
   intent.putExtras(bundle);
   setResult(RESULT_OK,intent);
   finish();
   }
});

//在A.Activity中加入,接受回调信息name
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data_intent){
super.onActivityResult(requestCode, resultCode, data_intent);
 if(resultCode == RESULT_CANCELED)
setTitle("cancel");
 else if (resultCode == RESULT_OK){
Bundle bundle = data_intent.getExtras();
if(bundle != null){
//获取b传送的数据
  String name = bundle.getString("name");
}
   }
}

Android 提供了包括 SharedPreferences 在内的很多种数据存贮方式,比如 SQLite,文件等,程序员可以通过这些 API 实现 Activity 之间的数据交换。如果必要,我们还可以使用 IPC 方式。

4、Activity的四种加载模式

Activity有四种加载模式,分别是:standard模式、singleTop模式、singleTask模式、singleInstance模式(其中standard模式和singleTop模式是一组、singleTask模式和singleInstance模式是一组),默认加载模式是standard模式。

四种加载模式的区别:

1、standard:标准模式(默认模式),一旦调用startActivity()方法就会产生一个新的Activity实例。 不需要在launchMode属性配置

/**
 * 默认(standard)加载模式
 *
 */
public class ActivityOne extends Activity implements OnClickListener
{
private TextView textView;// 显示文本
private Button button;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    textView = (TextView) findViewById(R.id.textView);
    button = (Button) findViewById(R.id.button);
    button.setText("go to ActivityOne");
    button.setOnClickListener(this);
    textView.setText(this + "");
}

@Override
public void onClick(View v)
{
    Intent intent = new Intent();
    intent.setClass(ActivityOne.this, ActivityOne.class);// 跳转
    startActivity(intent);
}
}

AndroidManifset.xml文件配置:

<activity android:name="ActivityOne"
  android:label="@string/app_name">
    <intent-filter>
   <action android:name="android.intent.action.MAIN" />
   <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
</activity>

2、singleTop:如果Activity实例位于栈顶,就不产生新的实例,直接使用栈顶的实例,否则,就会产生一个新的实例。

例如:现在Task栈元素为A-B-C-D(D在栈顶),这时候给D发一个启动Intent,如果D是 “standard”模式的,则生成D的一个新实例,栈状态为A-B-C-D-D。如果D是singleTop模式的话,则不会生成D的新实例,栈状态仍为A-B-C-D。如果这时候给B发Intent的话,不管B的launchMode是“standard”还是“singleTop”,都会生成B的新实例,栈状态变为A-B-C-D-B。

/**
 * singleTop模式
 */
public class ActivityOne extends Activity implements OnClickListener
{
private TextView textView;// 显示文本
private Button button;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    textView = (TextView) findViewById(R.id.textView);
    button = (Button) findViewById(R.id.button);
    button.setText("go to ActivityOne");
    button.setOnClickListener(this);
    textView.setText(this + "");
}

@Override
public void onClick(View v)
{
    Intent intent = new Intent();
    intent.setClass(ActivityOne.this, ActivityOne.class);// 跳转
    startActivity(intent);
}
}

AndroidManifset.xml文件配置:

<activity
android:name="ActivityOne"
android:label="@string/app_name"
android:launchMode="singleTop">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

3、singleTask:每次调用都会使用这个实例,不会去产生新的实例了。

AndroidManifset.xml文件配置:

<activity
android:name="ActivityOne"
android:label="@string/app_name"
android:launchMode="singleTask">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ActivityTwo"
android:label="@string/app_name">
</activity>

4、singleInstance:跟singleTask模式基本上是一样,只有一个区别:在这个模式下的Activity实例与其他Activity处在不同的Task中,此实例所处的Task中只能有这个Activity实例,不能有其他的实例。

AndroidManifaset.xml文件配置:

<activity
android:name="ActivityOne"
android:label="@string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ActivityTwo"
android:label="@string/app_name"
android:launchMode="singleInstance">
</activity>

5、Activity的创建和启动

5.1、Activity的创建流程

Activity创建需要经历如下的步骤:

(1) 自定义Activity类名,继承Activity类或者其子类,使用AS开发,一般继承AppCompatActivity类

public class BaseActivity extends AppCompatActivity {}

(2) 重写onCreate方法,并在该方法中调用setContentView方法

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(View);
}

(3) 在AndroidManiFest.xml文件中注册Activity,必须要注册,不注册会报错

  <application
    android:name=".BaseApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".SplashActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

    </activity>
    <activity android:name=".MainActivity" />
    <activity android:name=".BaseActivity" />
    <activity android:name=".activity.AboutCSDNActivity" />
    <activity android:name=".activity.BlogOsphereActivity" />
    <activity android:name=".activity.FeedBackActivity" />
    <activity android:name=".activity.WebActivity" />
    <activity android:name=".activity.AllBloggerActivity" />
    <activity android:name=".activity.BlogDetailActivity" />
</application>

(4) 启动Activity,通过调用startActivity(Intent)启动。

Intent intent = new Intent(getApplicationContext(), BlogDetailActivity.class);
   intent.putExtra("username", blogOspheres.get(position).getUserName());
   intent.putExtra("name", blogOspheres.get(position).getName());
   startActivity(intent);

(5) 销毁Activity,通过调用Finish()方法

        @Override
        public void onClick(View v) {
            finish();
        }

5.2、Activity启动的几种方式

第一种:显示启动

startActivity(new Intent(当前Activity,要启动的Activity.class));

//通过intent的ComponentName启动
ComponentName componentName = new ComponentName("当前Activity的全限定类名","启动Activity的全限定类名") ;
Intent intent = new Intent() ;
intent.setComponent(componentName) ;
startActivity(intent) ;

Intent intent = new Intent("android.intent.action.MAIN");
intent.setClassName("当前Activity的全限定类名","启动Activity的全限定类名");
startActivity(intent);

第二种:隐式启动

<activity
android:name="com.example.android.tst.SecondActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="com.example.android.tst.SecondActivity"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Intent intent=new Intent("com.example.android.tst.SecondActivity");
startActivity(intent);

第三种:启动APK

Intent intent = getPackageManager().getLaunchIntentForPackage
("apk第一个启动的Activity的全限定类名") ;
if(intent != null) startActivity(intent) ;

6、系统给我们提供的Activity

以下是Android系统给我们提供的常用的Activity

拨打电话

Uri uri = Uri.parse("tel:10010");
Intent intent = new Intent(Intent.ACTION_DIAL, uri);
startActivity(intent);

发送短信

Uri uri = Uri.parse("smsto:10010");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
intent.putExtra("sms_content", "Hello");
startActivity(intent);

发送彩信

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra("sms_body", "Hello");
Uri uri = Uri.parse("content://media/external/images/media/23");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("image/png");
startActivity(intent);

打开浏览器:

Uri uri = Uri.parse("http://www.baidu.com");
Intent intent  = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

发送电子邮件

Uri uri = Uri.parse("mailto:[email protected]");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(intent);

// 给[email protected]发邮件发送内容为“Hello”的邮件
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, "[email protected]");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Hello");
intent.setType("text/plain");
startActivity(intent);
// 给多人发邮件
Intent intent=new Intent(Intent.ACTION_SEND);
String[] mailTos = {"[email protected]", "[email protected]"}; // 收件人
String[] copyTos = {"[email protected]", "[email protected]"}; // 抄送
String[] secretTos = {"[email protected]", "[email protected]"}; // 密送
intent.putExtra(Intent.EXTRA_EMAIL, mailTos);
intent.putExtra(Intent.EXTRA_CC, copyTos);
intent.putExtra(Intent.EXTRA_BCC, secretTos);
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Hello");
intent.setType("message/rfc822");
startActivity(intent);

显示地图:

Uri uri = Uri.parse("geo:23.20,113.30");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

多媒体播放:

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/music.mp3");
intent.setDataAndType(uri, "audio/mp3");
startActivity(intent);

获取SD卡下所有音频文件,然后播放第一首

Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

打开摄像头拍照:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);

// 取出照片数据
Bundle extras = intent.getExtras();
Bitmap bitmap = (Bitmap) extras.get("data");

另一种:
调用系统相机应用程序,并存储拍下来的照片
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
time = Calendar.getInstance().getTimeInMillis();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment
.getExternalStorageDirectory().getAbsolutePath()+"/tucue", time + ".jpg")));
startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE);

获取并剪切图片

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.putExtra("crop", "true"); // 开启剪切
intent.putExtra("aspectX", 1); // 剪切的宽高比为1:2
intent.putExtra("aspectY", 2);
intent.putExtra("outputX", 20); // 保存图片的宽和高
intent.putExtra("outputY", 40);
intent.putExtra("output", Uri.fromFile(new File("/mnt/sdcard/temp"))); // 保存路径
intent.putExtra("outputFormat", "JPEG");// 返回格式
startActivityForResult(intent, 0);

剪切特定图片

Intent intent = new Intent("com.android.camera.action.CROP");
intent.setClassName("com.android.camera", "com.android.camera.CropImage");
intent.setData(Uri.fromFile(new File("/mnt/sdcard/temp")));
intent.putExtra("outputX", 1); // 剪切的宽高比为1:2
intent.putExtra("outputY", 2);
intent.putExtra("aspectX", 20); // 保存图片的宽和高
intent.putExtra("aspectY", 40);
intent.putExtra("scale", true);
intent.putExtra("noFaceDetection", true);
intent.putExtra("output", Uri.parse("file:///mnt/sdcard/temp"));
startActivityForResult(intent, 0);

进入手机设置界面:

Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);
startActivityForResult(intent, 0);

安装apk应用:

Uri installUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

卸载apk应用:

Uri uri = Uri.fromParts("package", packageName, null);
Intent it = new Intent(Intent.ACTION_DELETE, uri);
startActivity(it);

打开联系人:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(People.CONTENT_URI);
startActivity(intent);

查看指定联系人:

Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);//info.id联系人ID
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(personUri);
startActivity(intent);

7、Activity的安全退出

两种方法:

第一种:写一个BaseActivity,项目中所有的Activity都继承于这个BaseActivity,在BaseActivity中记录每一个Activity,退出应用的时候将所有的Activity销毁

 //用一个集合管理所有的activity
public final static LinkedList<BaseActivity> mBaseActivities = new LinkedList<BaseActivity>();
public static BaseActivity mBaseActivity;

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    synchronized (mBaseActivities) {
        mBaseActivities.add(this);
    }
}

 @Override
protected void onResume() {
super.onResume();
mBaseActivity = this;
}

@Override
protected void onPause() {
super.onPause();
mBaseActivity = null;
}

@Override
protected void onDestroy() {
    super.onDestroy();
    synchronized (mBaseActivities) {
        mBaseActivities.remove(this);
    }
}

//安全退出程序
public static void exitApp() {
    LinkedList<BaseActivity> activityCopy;
    //复制一份activity
    synchronized (mBaseActivities) {
        activityCopy = new LinkedList<BaseActivity>(mBaseActivities);
    }
    for (BaseActivity baseActivity : activityCopy) {
        baseActivity.finish();
    }
    //杀死当前进程
    android.os.Process.killProcess(android.os.Process.myPid());
}

第二种方法:退出的时候发送广播,销毁所有的Activity

8、Activity切换动画设置

在Activity切换的时候设置切换动画有两种方式:

第一种:在Activity跳转的时候设置,即是在startActivity方法之后设置,代码如下:

A.Activity跳转到B.Activity时,在startActivity()方法后面设置

 //第一个参数是activity离开时的动画,第二个参数是activity进入时的动画
 overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);

B.Activity回转到A.Activity时,在Finish()方法后面设置

finish();
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);

优化思路:可以将整个应用里面Activity相同的操作抽取到一个类里面,在BaseActivity中实例化,每一次设置动画或者进行Activity相关操作(比如,Activity跳转、传递参数等),直接调用方法即可,代码如下:

public class Opration {

private Intent mIntent = new Intent();
private Activity mContext = null;
private BaseApplication application = null;

public Opration(Activity mContext) {
    this.mContext = mContext;
    application = (BaseApplication) this.mContext.getApplicationContext();
}

/**
 * 跳转Activity
 *
 * @param activity 需要跳转至的Activity
 */
public void forward(Class<? extends Activity> activity) {
    mIntent.setClass(mContext, activity);
    mContext.startActivity(mIntent);
    mContext.overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain);
}

/**
 * 设置传递参数
 *
 * @param key   参数key
 * @param value 数据传输对象
 */
public void addParameter(String key, Bundle value) {
    mIntent.putExtra(key, value);
}

/**
 * 设置传递参数
 *
 * @param key   参数key
 * @param value 数据传输对象
 */
public void addParameter(String key, String value) {
    mIntent.putExtra(key, value);
}
}

第二种设置切换动画的方法:在样式文件里面设置

<!-- 默认Activity跳转动画 -->
<style name="change_animation"  parent="@android:style/Animation.Activity">
 <!-- 从A.Activity跳转到B.Activity时B.Activity的进入动画 -->
<item name="android:activityOpenEnterAnimation">@anim/default_anim_in</item>
<!-- 从A.Activity跳转到B.Activity时A.Activity的退出动画 -->
<item name="android:activityOpenExitAnimation">@anim/anim_stay</item>
<!-- 从B.Activity跳转到B.Activity时A.Activity的进入动画 -->
<item name="android:activityCloseEnterAnimation">@anim/anim_stay</item>
<!-- 从B.Activity跳转到B.Activity时B.Activity的退出动画 -->
<item name="android:activityCloseExitAnimation">@anim/default_anim_out</item>
</style>

修改Theme

<style name="AppTheme"  parent="@android:style/Theme.Light">
<item name="android:windowAnimationStyle">@style/change_animation</item>
<item name="android:windowNoTitle">true</item>
</style>

最后在AndroidManifest.xml文件中设置:

<application
   android:icon="@drawable/logo"
   android:label="@string/app_name"
   android:theme="@style/AppTheme" >

9、Activity其他设置

9.1、横竖屏切换问题

  在Android中,默认状态下APP横竖屏切换的时候会销毁当前的Activity实例,然后重新创建Activity实例,横竖屏切换时Activity的生命周期方法顺序是:onPause-> onStop-> onDestory-> onCreate->onStart->onResume。在一些特殊情况下,我们需要对横竖屏切换进行一些处理,以下是常用的处理:

禁止屏幕横竖屏切换

在AndroidManifest.xml中为Activity添加一个属性:android:screenOrientation, 这个属性有下述可选值:

  • unspecified:默认值 由系统来判断显示方向.判定的策略是和设备相关的,所以不同的设备会有不同的显示方向。
  • landscape:横屏显示(宽比高要长)
  • portrait:竖屏显示(高比宽要长)
  • user:用户当前首选的方向
  • behind:和该Activity下面的那个Activity的方向一致(在Activity堆栈中的)
  • sensor:有物理的感应器来决定。如果用户旋转设备这屏幕会横竖屏切换。
  • nosensor:忽略物理感应器,这样就不会随着用户旋转设备而更改了(”unspecified”设置除外)。
横竖屏切换的时候加载不同的布局

1)准备两套不同的布局,Android会自己根据横竖屏加载不同布局: 创建两个布局文件夹:layout-land横屏,layout-port竖屏 然后把这两套布局文件放在这两个文件夹里,文件名一样,Android就会自行判断,然后加载相应布局了!

2 )自己在代码中进行判断

我们一般是在onCreate()方法中加载布局文件的,我们可以在这里对横竖屏的状态做下判断,关键代码如下:

if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
 setContentView(R.layout.横屏);
}  

else if (this.getResources().getConfiguration().orientation ==Configuration.ORIENTATION_PORTRAIT) {
setContentView(R.layout.竖屏);
}
状态保存问题

通过一个Bundle savedInstanceState参数即可完成,有三个核心方法:

onCreate(Bundle savedInstanceState);
onSaveInstanceState(Bundle outState);
onRestoreInstanceState(Bundle savedInstanceState);

在onSaveInstanceState(Bundle outState);里面将需要保存的数据放入到Bundle里面,然后在 onCreate(Bundle savedInstanceState);或者onRestoreInstanceState(Bundle savedInstanceState);中将数据取出。

注意:取出数据的时候要进行判空操作。

时间: 2024-10-27 03:10:30

Android学习笔记四之Activity的相关文章

Android学习笔记四:添加Source

问题描述 Source not foundThe JAR file D:\.....\sdk\platforms\android-20\android.jar has no source attachment. 问题原因及解决办法 1. 使用SDK Manager下载最新版本的Sources for Android SDK 一般文件下载目录默认在SDK下的sources文件中即 \adt-bundle-windows-x86_64-20130522\sdk\sources\android-20

Android 学习笔记四:创建工具栏按钮

原文:http://blog.csdn.net/lihongxun945/article/details/48951199 前面我们已经可以在一个Activity中添加一些按钮之类的组件.由于手机的屏幕很小,所以很多时候我们会需要用到工具栏,通过下拉菜单之类的方式来节省空间. Android 提供了对工具栏按钮的强大支持. 增加一个工具栏按钮 我们现在给 MainActivity 增加一个搜索按钮.增加一个按钮需要做这三件事 一,在 res/menu/activity_main.xml 中增加一

Android学习笔记(四)

2.      Settings.System.getInt(ContentResolvercr, String name, int def)方法从系统设置(settings)参数的集合中取出名称为name的参数的参数值,如果系统设置中没有该参数,则返回默认值def. 3.      Activity的函数setVolumeControlStream(intstreamType)用于设置所在Activity中音量控制键控制的音频流,一般在onCreate()函数中设定.其中,streamType

Android学习笔记—第九章 Activity的加载模式

第九章 Activity的加载模式 task:类似于栈,每次打开界面会创建一个task,然后将这开启的界面放入到该task中. (1)standard:默认模式 每次都会创建一个新的界面,将该界面加入task中 (2)singleTop:栈顶单实例模式 a. 如果目标Activity不存在,创建一个新的Activity,存入到task中 b. 如果目标Activity已经存在,并且处于栈顶,不会再创建新的Activity c. 如果目标Activity已经存在,但不处于栈顶,创建一个新的Acti

十四、Android学习笔记_Android回调函数触发的几种方式 广播 静态对象

一.通过广播方式: 1.比如登录.假如下面这个方法是外界调用的,那么怎样在LoginActivity里面执行登录操作,成功之后在回调listener接口呢?如果是平常的类,可以通过构造函数将监听类对象传入即可.但是在Activity中不能传递监听对象,所以考虑使用广播来实现. public void login(final LoginOnClickListener listener) { Intent intent = new Intent(context, LoginActivity.clas

【转】 Pro Android学习笔记(七四):HTTP服务(8):使用后台线程AsyncTask

目录(?)[-] 5秒超时异常 AsyncTask 实现AsyncTask抽象类 对AsyncTask的调用 在哪里运行 其他重要method 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载须注明出处:http://blog.csdn.net/flowingflying/ 之前,我们直接在activity中执行http通信,在通信过程中可能会出现连接超时.socket超时等情况,超时阈值一般是秒级,例如AndroidHttpClient中设置的20秒,如果出现超时,就

【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版

目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖排时,如下图显示: 屏幕上只显示一个fragment,点击列表上的数目,进入到简介的activity.下面介绍实现的方式. 设置横排和竖排的不同排版风格 在 Pro Android学习笔记(四):了解Android资源(下)的“资源和配置的变更”中,我们介绍了如何同资源文件夹名设置不同资源.缺省的l

Android学习笔记(四) Fragment

1.从网上看了许多篇关于Fragment的简要介绍,发现都是相类似的理解,而且都是草草地说与Activity大致相同就了事,都没有说清楚Activity与Fragment的具体的关联与区别,一大堆的rubbish. 在此我也记录下本人的rubbish理解: 关于Fragment的生命周期问题,确实应该是如大多数人所说,与Activity相类似,用法也相类似,但是这并不足以教会我们怎样去使用Fragment. Fragment应该是作为Activity的一部分,更像动态的panel(也许实际上真的

Android学习笔记二十四之ListView列表视图二

Android学习笔记二十四之ListView列表视图二 前面一篇我们介绍了常用的几种适配器的简单实现和ListView的简单使用,这一篇中,我们介绍一下ListView的优化和一些其它的问题. ListView优化方法一 在ListView中,我们最常用的就是自定义Adapter,在我们自定义Adapter中,需要实现两个比较重要的方法getCount()和getView(),前者是负责计算ListView的总Item数,后者是生成Item,有多少个Item就会调用getView()方法多少次