《第一行代码--Android》读书笔记之日志工具Log与Activity

日志工具Log

Log.v(String tag,String msg);//verbose级别,最琐碎
Log.d(String tag,String msg);//debug级别,调试程序分析问题
Log.i(String tag,String msg);//info级别,帮助分析用户行为
Log.w(String tag,String msg);//warn级别,警告信息
Log.e(String tag,String msg);//error级别,打印错误信息

下面给出本书后面的自定义日志工具类,方便开发调试使用打印日志和发布打包的时候屏蔽日志

import android.util.Log;
public class LogUtil {
    public static final int VERBOSE=1;
    public static final int DEBUG=2;
    public static final int INFO=3;
    public static final int WARN=4;
    public static final int ERROR=5;
    public static final int NOTHING=6;
    public static final int LEVEL=VERBOSE;
    //LEVEL设置为VERBOSE表示级别最高,此工具类会打印所有信息,设置成NOTHING,此工具类不会打印任何日志
    public static void v(String tag,String msg){
        if (LEVEL<=VERBOSE){
            Log.v(tag,msg);
        }
    }
    public static void d(String tag,String msg){
        if (LEVEL<=DEBUG){
            Log.d(tag,msg);
        }
    }
    public static void i(String tag,String msg){
        if (LEVEL<=INFO){
            Log.i(tag,msg);
        }
    }
    public static void w(String tag,String msg){
        if (LEVEL<=WARN){
            Log.w(tag,msg);
        }
    }
    public static void e(String tag,String msg){
        if (LEVEL<=ERROR){
            Log.e(tag,msg);
        }
    }
}

Activity

Activity的创建与注册

创建:1.新建一个布局文件(xml)
2.新建一个.java文件,自定义类继承自Activity,重写onCreate()函数

public class BaseActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        //隐藏活动标题栏
        requestWindowFeature(Window.FEATURE_NO_TITLE);      
        //Log.d("BaseActivity", getClass().getSimpleName());
        setContentView(R.layout.first_layout);
    }

最后别忘了注册哦,在AndroidManifest文件的< application >标签内注册activity

        <activity
            android:name=".FirstActivity"
            android:launchMode="singleTask"
            android:label="This is FirstActivity!">
            <intent-filter>//若这是一个主活动,需要这样写
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

在Activity中使用Menu

1.在res文件夹中创建一个menu文件夹→创建Android XML File
→在activity中重写onCreateOptionsMenu(Menu menu)
→重写public boolean onOptionsItemSelected(MenuItem item)编写响应菜单项代码
Android XML File:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:id="@+id/add_item"
    android:title="Add"/>
    <item
        android:id="@+id/remove_item"
        android:title="Remove"/>
</menu>

activity.java:

public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.add_item:
                Toast.makeText(FirstActivity.this, "you clicked Add", Toast.LENGTH_SHORT).show();
                break;
            case R.id.remove_item:
                Toast.makeText(FirstActivity.this, "you clicked Remove", Toast.LENGTH_SHORT).show();
            default:
                break;
        }
        return true;
    }

Intent之于活动

创建Activity

显式Intent:

                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);

隐式Intent:
含蓄的Intent需要指定一系列action和category等信息,只有AndroidManifest的< activity>中< action>和< category>与intent的action和category完全匹配才能启动该activity。

<action android:name="com.example.activitytest.ACTION_START"/>
                <category android:name="com.example.activitytest.MY_CATEGORY"/>
Intent intent=new Intent("com.example.activitytest.ACTION_START");              intent.addCategory("com.example.activitytest.MY_CATEGORY");

隐式intent还可以用来启动其他程序的活动
在< intent-filter>标签中在配置一个< data>标签

Intent intent1=new Intent(Intent.ACTION_VIEW);
intent1.setData(Uri.parse("http://www.baidu.com"));
//<data android:scheme="http"/> 在AndroidManifest中配置
Intent intent=new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
<data android:scheme="tel"/>
startActivity(intent1);

Intent传递数据的使者

1、可以通过intent.putExtra(String keyname, String value) 把数据暂存到intent中,启动到另一个活动后,再把数据通过键值从intent中取出。

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
String data="Hello SecondActivity";
intent.putExtra("extra_data",data);
startActivity(intent);
Intent intent=getIntent();
String data=intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);

2、返回数据给上一个活动
这里写图片描述
父活动:

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent,1);//第二个参数是请求码

子活动:

                Intent intent = new Intent();
                String data = "Hello FirstActivity";
                intent.putExtra("data_return", data);             
                setResult(RESULT_OK, intent);//专用于向上一个活动返回数据,第一个参数是用于向上一个活动返回处理结果,一般是RESULT_OK,RESULT_CANCELED
                finish();//销毁活动,回调onActivityResult,可以在此方法得到返回数据。

//按返回键销毁活动的回调函数
    @Override
    public void onBackPressed(){
        Intent intent=new Intent();
        intent.putExtra("data_return","Hello FirstActivity");
        setResult(RESULT_OK, intent);
        finish();
    }

父活动中重写此活动,得到返回的数据:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case 1:
                if (resultCode == RESULT_OK) {
                    String returnedData = data.getStringExtra("data_return");
                    Log.d("FirstActivity", returnedData);
                }
                break;
            default:
                break;
        }
    }

这里写图片描述
—-图来自android编程权威指南
3、我们还可以通过intent来传递对象
(a)、Serializable方式,将整个对象序列化。
只需要让该对象implement Serializable接口,写一系列set,get方法来为对象的数据做赋值和读取。
比如,FirstActivity:

Person person=new Person();
person.setName("TellH");
Person.setAge(20);
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("person_data",person):///假如Person类已经实现了Serializable接口
startActivity(intent);

SecondActivity:

Person person=(Person)getIntent().getSerializableExtra("person_data");

(b)、Parcelable方式:

public class Person implements Parcelable {
    private String name;
    private int age;
    //需要重写一下两个方法
    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {//将数据一一打包,写入Parcel
        dest.writeString(name);
        dest.writeInt(age);
    }
    //创建一个Parcelable.Creator<Person>接口的实现,重写两个方法
    private static final Parcelable.Creator<Person> CREATOR=new Parcelable.Creator<Person>(){
        @Override
        public Person createFromParcel(Parcel source) {//从Parcel读取数据
            Person person= new Person();
            //这里的读出数据的顺序一定要和写入数据的顺序要一致
            person.name=source.readString();
            person.age=source.readInt();
            return person;
        }
        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

这里深入了解一下intent的通信:
intent对象是component用来与操作系统通信的一种媒介工具。当调用startActivity()方法是,该方法把intent发送给操作系统的ActivityManager,ActivityManager负责创建Activity实例并调用其onCreate()方法,这种模式会使在不同应用间的Activity的交互变得容易得多。

活动的生命周期

1、返回栈(back stack==Task)
Task是一个具有栈结构的对象,一个Task就是一组activity的集合。这些activity按照它们打开的顺序被放置于一个先进后出的栈中(back stack)。用户点击图标打开一个app时,该app的task会被移到前台显示。如果当前没有该app的task,系统将会新建一个task并在其中运行Main activity。如果HOME键被按下,从当前app回到桌面,该app的Task会被移到后台,后台的task所属的所有activity都是stop状态,且back stack依然存在——这个task其实只是失去了和用户交互的焦点。
这里写图片描述

taskAffinity属性:每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。而Task也有自己的affinity属性,它的值等于它的根Activity的taskAffinity的值。

Task与Activity,application的关系:
Task与Activity,application的关系
2、活动生存期
(a)、当任务被创建和销毁分别会回调onCreate()和onDestroy()
(b)、当任务进入前台或者解锁屏(由不可见到可见)和退出前台进入后台或者被锁屏(由可见到不可见)时分别会回调onStart()和onStop()
(c)、当任务(位于返回栈的栈顶)要准备与用户进行交互的时候回调onResume();
但当任务要准备被另一个活动或对话框覆盖,需要释放掉系统资源,保存关键数据,回调onPause(),此时任务仍然可见,但不能与用户进行交互。
(d)、但任务从stop状态变为start状态前,先回调onRestart()。
(e)、其他的Activity状态方法
onWindowFocusChanged方法:在Activity窗口获得或失去焦点时被调用,例如创建时首次呈现在用户面前;当前Activity被其他Activity覆盖;当前Activity转到其他Activity或按Home键回到主屏,自身退居后台;用户退出当前Activity。
onSaveInstanceState:(1)在Activity被覆盖或退居后台之后,系统资源不足将其杀死,此方法会被调用,此方法会被调用,此方法携带一个Bundle类型的参数,利用bundle.putString(或者putInt,put~)向bundle写入数据,在onCreate(Bundle savedInstanceState),或者onRestoreInstanceState(Bundle savedInstanceState),中获取数据,恢复之前活动被回收的状态;(2)在用户改变屏幕方向时,此方法会被调用;(3)在当前Activity跳转到其他Activity或者按Home键回到主屏,自身退居后台时,此方法会被调用。onSaveInstanceState的调用顺序是在onPause之前。

onRestoreInstanceState:(1)在Activity被覆盖或退居后台之后,系统资源不足时被回收,然后用户又回到了此Activity;(2)在用户改变屏幕方向时,重建的过程中,此方法会被调用。我们可以重写此方法,以便可以恢复一些临时数据。onRestoreInstanceState的调用顺序是在onStart之后。
这里写图片描述
这里写图片描述

活动的启动模式

在AndroidManifest中注册活动的时候配置,< activity android:launchMode=”?”>
(a)、standard,默认模式,每次启动该活动都会创建并往返回栈栈顶添加该活动的实例
(b)、singleTop,启动该活动前检查返回栈栈顶是否有该活动的实例,若有直接使用栈顶的实例,否则常见病往返回栈栈顶添加该活动的实例
(c)、singleTask,每次启动该活动前都会先检查是否存在与它的taskAffinity相同的Task。若存在该Task,检查Task是否有该活动的实例,若有直接使用栈顶的实例,并把这活动之上的所有活动统统出栈,否则创建并往返回栈栈顶添加该活动的实例,将该Task调到前台;若无则新建Task和该Activity实例,入栈。
这里写图片描述

(d)、singleInstance, 当要启动该活动时,如果该Activity没有被实例化,那么就重新创建一个Task并入栈,并保证不再有其他Activity实例进入(即这个task中永远只有一个activity),以便于其他应用程序共享该实例。如果已经被实例化,那么就调用该Activity的onNewIntent;任何从该Activity加载的其它Actiivty(假设为Activity2)都会被放入其它的Task中,如果存在与Activity2相同affinity的Task,则在该Task内创建Activity2。如果不存在,则重新生成新的Task并入栈。
singleInstance与singleTask的区别在于一个Task内只有一个Instance,活动的启动过程都是相似的。

启动活动的最佳写法

在SecondActivity中添加一个actionStart()方法

    public static void actionStart(Context context,String param1,String param2){
        Intent intent=new Intent(context,SecondActivity.class);
        intent.putExtra("param1",param1);
        intent.putExtra("param2",param2);
        context.startActivity(intent);
    }

随时随地退出程序

用一个List< Activity>管理Activity。

public class ActivityCollector{
    public static List<Activity> activities=new ArrayList<>();
    public static void addActivity(Activity activity){//在每次onCreate()调用
        activities.add(activity);
    }
    public static void removeActivity(Activity activity){//在每次onDestroy()调用
        activities.remove(activity);
    }
    public static void finishAll(){
        for(Activity activity:activities){
            if(!activity.isFinishing()){
                activity.finish();
                activities.remove(activity);
            }
        }
    }

查阅和参考的资料:
基础总结篇之一:Activity生命周期:http://blog.csdn.net/liuhe688/article/details/6733407
基础总结篇之二:Activity的四种launchMode:http://blog.csdn.net/liuhe688/article/details/6754323
Android开发中任务和返回栈:http://www.android100.org/html/201402/22/5690.html
Android中的“Application”,“Task”,“Activities”的关系:http://blog.csdn.net/mengweiqi33/article/details/7670541
Activity的taskAffinity属性:http://blog.csdn.net/wangshione/article/details/8491249

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值