2015.11.13-11.17
平台。
Windows 10
Android Studio 1.3.2
看“Android.老罗”的笔记以为Android开发入门的好瓜笔记,笔记保存地址:DataTransferSimple。
官方相关文档。
开发手册:http://developer.android.com/training/index.html
类参考:http://developer.android.com/reference/packages.html
2015.11.13
由“管理活动生命周期”文档可知:系统会根据用户操作自动调用相应的回调方法来让活动处于相应的生命周期。探索活动生命周期中的每一个阶段与用户的哪一个操作对应(用户的什么操作会引起系统调用什么样的函数)。使用安卓的“日志工具LogCat”来探索。
注:欲知活动在生命周期中每个阶段的栈内存数据见“管理活动生命周期”。
以“Blank Activity”为模板创建的工程以“.MainActivity”为主活动(见AndroidManifest.xml文件),即用户在设备上运行应用程序首先启动的活动。在主活动对应的类中用logcat输出的形式重写各生命周期函数。打开MAinActivity.java文件:
/* MAinActivity.java */
//……
import android.util.Log; //Alt + Enter
//……
public class MainActivity extends AppCompatActivity {
private static final String ACTIVITY_TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(ACTIVITY_TAG, "onCreate ");
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
Log.i(ACTIVITY_TAG, "onStart ");
}
@Override
protected void onResume() {
super.onResume();
Log.i(ACTIVITY_TAG, "onResume ");
}
@Override
protected void onPause() {
super.onPause();
Log.i(ACTIVITY_TAG, "onPause ");
}
@Override
protected void onStop() {
super.onStop();
Log.i(ACTIVITY_TAG, "onStop ");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(ACTIVITY_TAG, "onRestart ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(ACTIVITY_TAG, "onDestroy ");
}
//……
}
[1] 活动生命周期的7个方法
关于活动生命周期的7个方法可从“管理活动生命周期”看来,官网图如下:
在AS中敲这几个方法时,会自动匹配弹出来。
[2] @Override
重写父类中可重写方法的标签。
- 编译器根据@Override标签检查其后跟随的方法是否为父类中的方法(若无此标签,编译器不会检查)。
- 编译器还会根据@Override标签检查其后跟随的方法是否可被重写。
- 告知读者此为重写方法。
[3] super
super代指父类,“super.method();”表示调用父类的method()。“super();”或“super(param);”表示调用父类中具相同形式的构造函数。
[4] Log.i()
见Log类。
i()是Log类中的一个方法,以上代码使用的i()方法为:
public static int i (String tag, String msg)
Send an INFO log message.Parameters
tag
Used to identify the source of a log message. It usually identifies the class or activity where the log call occurs.msg
The message you would like logged.
“Send an INFO log message”中的INFO是Log类中值为4的内部常量,在i()函数中INFO被传递给println_native()函数(http://blog.csdn.net/luoshengyang/article/details/6581828),故而称Log.i()输出INFO日志信息。
[5] private static final String ACTIVITY_TAG = “MainActivity”;
此语句为Log.i()第一个参数定义的实参。简单看一下java中相关关键字的含义:
访问控制
所有类成员的默认访问范围都是 package 访问,也就是说,除非存在特定的访问控制修饰符,否则,可以从同一个包中的任何类访问类成员。
private 关键字是访问控制修饰符,可以应用于类、方法或字段(在类中声明的变量)。 只能在声明 private(内部)类、方法或字段的类中引用这些类、方法或字段。在类的外部或者对于子类而言,它们是不可见的。
protected 关键字是可以应用于类、方法或字段(在类中声明的变量)的访问控制修饰符。可以在明 protected 类、方法或字段的类、同一个包中的其他任何类以及任何子类(无论子类是在哪个包中声明的)中引用这些类、方法或字段。
public 关键字是可以应用于类、方法或字段(在类中声明的变量)的访问控制修饰符。 可能只会在其他任何类或包中引用 public 类、方法或字段。
类、方法和变量修饰符
final 关键字可以应用于类,以指示不能扩展该类(不能有子类)。final 关键字可以应用于方法,以指示在子类中不能重写此方法。final变量即为常量,只能赋值一次。static 关键字可以应用于内部类(在另一个类中定义的类)、方法或字段(类的成员变量)。 通常,static 关键字意味着应用它的实体在声明该实体的类的任何特定实例外部可用。static(内部)类可以被其他类实例化和引用(即使它是顶级类) static 字段(类的成员变量)在类的所有实例中只存在一次。 可以从类的外部调用 static 方法,而不用首先实例化该类。这样的引用始终包括类名作为方法调用的限定符。
源文档 http://blog.csdn.net/hfmbook/article/details/7634385
[6] 运行
用安卓系统的手机(华为 荣耀7)连接PC,在AS中将以上程序运行并将其下载到荣耀7中[解决ADB not responding. if you’d like to……错误:在CMD中输入netstat -aon | findstr “5037”,将此命令运行结果中的进程号对应的进程结束]。对用户不同操作得到以下输出:
图1.活动生命周期方法与用户操作的对应。
活动生命周期方法都可被开发这重新,官方开发文档“管理活动生命周期”有对每个函数的内容进行建议。
2015.11.14
Intent提供了在运行时的绑定机制,它能够在程序运行时连接两个不同的组件。它最大的价值是在活动中启动新的活动。Intent负责对应用中一次操作的“动作”、“动作涉及的数据”以及“附加数据”进行描述,通过Intent可以向Android系统表达请求或意愿,系统会根据Intent的描述来选择、调用合适的组件响应此请求。
Intent内含动作-数据(action-data)对属性:
- action:常见动作,如ACTION_VIEW、ACTION_EDIT、ACTION_MAIN等。
- data:完成此动作需要传递的数据。
Intent除了以上两个属性之外,还有以下属性:
Intent的各属性的取值可在Intent的Reference手册中查询。
再看一遍视频,学习如何用代码来实现Intent传递数据的功能。
(1) 功能描述
看完视频,实现如下功能:在主活动中增加一个按钮;当用户点击此按钮跳转到另外一个活动中并在另外一个活动中显示用Intent(静态变量、全局变量以及剪切板)传递过来的数据,此数据来自用户输入。
(2) 代码实现
打开昨天用AS建立的工程。
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<EditText
android:id="@+id/eMsg"
android:layout_weight="1"
android:layout_width="0"
android:layout_height="wrap_content"
android:hint="@string/hMsg" />
<Button
android:id="@+id/bSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send" />
</LinearLayout>
各空间内的属性含义见pAdTy_-9 构建一个简单的用户界面和活动(Activity)。(hMsg在/values/string.xml中定义)
MainActivity.java
//…...
public class MainActivity extends AppCompatActivity {
private static final String ACTIVITY_TAG = "MainActivity";
private Button bSend;
private EditText eMsg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(ACTIVITY_TAG, "onCreate ");
setContentView(R.layout.activity_main);
//获取所加载的activity_main布局文件中的控件
bSend = (Button) this.findViewById(R.id.bSend);
eMsg = (EditText) this.findViewById(R.id.eMsg);
//为按钮创建一个点击事件-及点击事件的响应函数
bSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建启动另外一个活动的Intent
Intent intent = new Intent(MainActivity.this, ReciveIntentMsg.class);
//往Intent中添加数据
intent.putExtra("User enter data", eMsg.getText().toString());
//通过Intent启动另外一个活动
startActivity(intent);
}
});
}
//…...
}
在引入新的类时根据AS提示用“Alt + Enter”引入类的命名空间。
Intent有多种构造函数,关于Intent的方法、内部变量、常量等可具体可查看其手册。Intent的第二个参数ReciveIntentMsg.class是另外一个活动的类。接下来用AS工具创建此活动类(见pAdTy_-9 构建一个简单的用户界面和活动(Activity))。用AS工具创建活动,除生成在AS工具中指定的文件外,AS会自动将活动注册到应用程序的清单文件中,并为开发者生成活动类的基本模板。
R.java
在Android Studio中,R.java文件的位置如下:
R.java文件的内容是自动生成的。在项目中添加的任何资源都会在其中生成一个相应的资源id,供应用程序的其它文件引用。永远不要手动去修改它。
如在MainActivity.java文件中引用的“布局文件”和“在.xml文件中定义的变量”语句:
setContentView(R.layout.activity_main);
//获取所加载的activity_main布局文件中的控件
bSend = (Button) this.findViewById(R.id.bSend);
eMsg = (EditText) this.findViewById(R.id.eMsg);
R是引用xml文件或在其中资源的前缀,layout表示布局文件,id表示在xml中定义的资源的id号(见.xml文件中资源定义时的android:id属性),activity、bSend、eMsg在R.java中的位置:
activity_recive_intent_msg.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" //...... <TextView android:id="@+id/rMsg" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
ReciveIntentMsg.java
//…...
public class ReciveIntentMsg extends AppCompatActivity {
private TextView rMsg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recive_intent_msg);
//获取父活动传递过来的Intent
Intent intent = getIntent();
String str = intent.getStringExtra("User enter data");
//获取所加载的布局文件的文本控件
rMsg = (TextView)this.findViewById(R.id.rMsg);
rMsg.setText("User enter data:" + str);
}
//…...
}
Intent传递数据将数据整理为键-值对的形式。故而此处只需根据值的键即可找到对应的值。
(3) 运行
将安卓设计连接到PC上,在AS中点击运行按钮(设置为在真机上运行)[解决ADB not responding. if you’d like to……错误:在CMD中输入netstat -aon | findstr “5037”,将此命令运行结果中的进程号对应的进程结束]:
图2.主活动启动并输入用户信息
图3. 将主活动传递过来的Intent中的信息显示在TextView中
2015.11.17
使用Intent可以很方便的在不同的Activity之间传递数据,但Intent无法传递不能序列化的对象。可以使用静态变量来解决此问题。
使用静态变量在活动之间传递数据的过程比较简单:在发送数据的活动中直接使用接收数据活动中的静态变量(给其赋予欲发送的数据)。然后用Intent启动接收数据的活动即可。如此,只需要在DataTransferSimple工程中添加几行代码即可完成。
ReciveIntentMsg.java
public class ReciveIntentMsg extends AppCompatActivity {
private TextView rMsg;
public static String psStr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recive_intent_msg);
//获取父活动传递过来的Intent
Intent intent = getIntent();
String str = intent.getStringExtra("User enter data");
//获取所加载的布局文件的文本控件
rMsg = (TextView)this.findViewById(R.id.rMsg);
rMsg.setText("User enter data:" + str + "\n" + "Static data" + psStr);
}
//…...
}
因psStr要被其它活动类所访问,故而需public访问控制属性,而使用static修饰只是为让psStr只存在一个实例。
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String ACTIVITY_TAG = "MainActivity";
private Button bSend;
private EditText eMsg;
@Override
protected void onCreate(Bundle savedInstanceState) {
//......
//为按钮创建一个点击事件-及点击事件的响应函数
bSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建启动另外一个活动的Intent
Intent intent = new Intent(MainActivity.this, ReciveIntentMsg.class);
//往Intent中添加数据
intent.putExtra("User enter data", eMsg.getText().toString());
//访问ReciveIntentMsg活动类中的公有静态变量,将数据直接复制与它
ReciveIntentMsg.psStr = "谁?";
//通过Intent启动另外一个活动
startActivity(intent);
}
});
}
//…...
}
连接安卓手机,在AS中点击运行按钮(设置在真机上运行),运行结果如下:
图1. 运行DataTransferSimple应用程序并往EditView控件中输入数据
图2.在图1中点击SEND按钮后跳转到活动ReciveIntentMsg中,第一行为intent携带的数据,第二行为静态变量带过来的数据
除非Android应用程序清除内存,否则全局变量application将一直可以被访问(参考application类参考)。
用全局变量传递数据的过程跟使用静态变量传递数据的过程极为类似:先定义一个继承于application的java 类的全部变量GlobalVaribleClass。任何活动类都可以对GlobalVaribleClass进行访问,只要发送数据的活动类先将数据放到全局变量GlobalVaribleClass中,接收数据的活动类即可马上访问此GlobalVaribleClass并获取数据。见具体代码实现。
在AS中,在MAinActivity的父目录上右键 >> New >> java Class,输入类名为GlobalVaribleClass。点击OK保存即会生成GlobalVaribleClass.java文件。
GlobalVaribleClass.java
package com.example.lxr.datatransfersimple;
import android.app.Application;
/** * Created by lxr on 2015/11/17. */
public class GlobalVaribleClass extends Application {
//本类的内部成员
public String name;
//本类的方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//当application启动时此方法被调用,在活动、服务以及接收对象(除内容提供器)被创建前调用
@Override
public void onCreate() {
super.onCreate();
setName("我");
}
}
继承于Application的类即可作为全局变量使用。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.lxr.datatransfersimple" >
<application android:name=".GlobalVaribleClass" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >
<activity android:name=".MainActivity" 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=".ReciveIntentMsg" android:label="@string/title_activity_recive_intent_msg" android:parentActivityName=".MainActivity" >
<meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.lxr.datatransfersimple.MainActivity" />
</activity>
</application>
</manifest>
在清单文件的标签下注册GlobalVaribleClass类。
MainActivity.java
public class MainActivity extends AppCompatActivity {
//……
//全局变量实例
private GlobalVaribleClass myApp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//……
//为按钮创建一个点击事件-及点击事件的响应函数
bSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//…...
//全局变量application
myApp = (GlobalVaribleClass)getApplication();
myApp.setName("Buddha");
//通过Intent启动另外一个活动
startActivity(intent);
}
});
}
//…...
}
在MainActivity.java中利用GlobalVaribleClass 来传递数据。
ReciveIntentMsg.java
public class ReciveIntentMsg extends AppCompatActivity {
//……
private GlobalVaribleClass myApp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//……
//获取application对象
myApp = (GlobalVaribleClass)getApplication();
//获取所加载的布局文件的文本控件
rMsg = (TextView)this.findViewById(R.id.rMsg);
rMsg.setText("User enter data:" + str + "\n" + "Static data" + psStr + "\n" + myApp.getName());
}
//…...
}
在ReciveIntentMsg.java中获取MainActivity活动传递过来的数据。
连接安卓手机到PC,在AS中运行程序得如下结果:
图1. 运行应用程序并往EditView控件中输入内容
图2.点SEND按钮后跳转到ReciveIntentMsg活动,并接收了Buddha信息
在Activity之间传递数据还可以使用剪切板技术,也就是一个程序将一些数据复制到剪切板上,然后其它的任何程序都可以从剪切板中获取数据。Android中有内置的剪切板。直接看代码实现。
MainActivity.java
public class MainActivity extends AppCompatActivity {
//…...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//……
//为按钮创建一个点击事件-及点击事件的响应函数
bSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//……
//剪切板
ClipboardManager clipboardManager = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
String name = "Buddha";
clipboardManager.setText(name);
//通过Intent启动另外一个活动
startActivity(intent);
}
});
}
//…...
}
ReciveIntentMsg.java
public class ReciveIntentMsg extends AppCompatActivity {
//…..
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//……
//剪切板
ClipboardManager clipboardManager = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
rMsg.setText("User enter data::" + str + "\n" + "Static data: " + psStr + "\n" + myApp.getName() + "\n"
+ "Only clipboard: " + clipboardManager.getText().toString());
}
//…...
}
在MainActivity.java中获取Android内置的剪切板并让剪切板中写入数据。在ReciveIntentMsg.java中根据上下文获取到剪切板,获取剪切板上的数据。
连接安卓手机到PC,在AS中运行程序,运行结果如下:
图1. 运行应用程序并往EditView控件中输入内容
图2.点击SEND按钮之后在ReciveIntentMsg活动中所接收到的数据
[2015.11.17-16:49]