Android开发 入门篇(一)

Android开发 入门篇(一),第1张

概述date:2020-01-0912:56:40文章目录序言新建项目的小问题build.gradle外层gradleappgradle日志工具活动创建和使用ToastmenuActivity跳转显示Intent隐式Intent向下传递数据返回数据给上一级活动生命周期活动状态活动的生命期活动启动模式活动的应用找到界面对应的活动快速

date: 2020-01-09 12:56:40

文章目录序言新建项目的小问题build.gradle外层gradleapp gradle日志工具活动创建和使用ToastmenuActivity跳转显示Intent隐式Intent向下传递数据返回数据给上一级活动生命周期活动状态活动的生命期活动启动模式活动的应用找到界面对应的活动快速直接退出程序启动程序的好技巧balabalaOK,THANKS FOR READING.BYE BYE~
有些as的使用技巧、活动和部分控件的使用。
出自《第一行代码(第二版)》,用于自己学(chao)习(shu)记录

序言新建项目的小问题

关于AS的一些小问题,如果如下报错

Error:Execution Failed for task ':app:preDeBUGAndroIDTestBuild'.> Conflict with dependency 'com.androID.support:support-annotations' in project ':app'. Resolved versions for app (26.1.0) and test app (27.1.1) differ. See https://d.androID.com/r/tools/test-apk-dependency-conflicts.HTML for details.

build.gradleModule:app文件中的dependencIEs{…}中添加

androIDTestCompile('com.androID.support:support-annotations:26.1.0') {    force = true}

即可,如果版本是其他,按照版本修改相应数值即可。

build.gradle

AS中是用gradle构建项目的,gradle是一个先进的项目构建工具。使用基于Groovy的领域特定语言(DSL)声明项目配置,摒弃了基于XML的繁琐配置。
项目中有两个build.gradle文件,一个是外层的,一个是内层app目录下的。

外层gradle
buildscript {        repositorIEs {        Google()        jcenter()    }    dependencIEs {        classpath 'com.androID.tools.build:gradle:3.0.0'    }}allprojects {    repositorIEs {        Google()        jcenter()    }}task clean(type: Delete) {    delete rootProject.buildDir}

repositorIEs中声明了Google()和jcenter(),jcenter()是一个代码托管仓库,里面有很多优秀的安卓开源项目,声明后可以轻松引用仓库中的开源项目。dependencIEs中声明了一个gradle插件,其实gradle不是专门为AndroID项目开发的,Java和C++中也可以使用,因此需要使用专门的插件。

app gradle
apply plugin: 'com.androID.application'androID {    compileSdkVersion 26    defaultConfig {        applicationID "com.example.k.androIDpractIE"        minSdkVersion 15        targetSdkVersion 26        versionCode 1        versionname "1.0"        testInstrumentationRunner "androID.support.test.runner.AndroIDJUnitRunner"    }    buildTypes {        release {            MinifyEnabled false            proguardfiles getDefaultProguardfile('proguard-androID.txt'), 'proguard-rules.pro'        }    }}dependencIEs {    implementation filetree(dir: 'libs', include: ['*.jar'])    implementation 'com.androID.support:appcompat-v7:26.1.0'    implementation 'com.androID.support.constraint:constraint-layout:1.1.3'    testImplementation 'junit:junit:4.12'    androIDTestImplementation 'com.androID.support.test:runner:1.0.2'    androIDTestImplementation 'com.androID.support.test.espresso:espresso-core:3.0.2'    androIDTestCompile('com.androID.support:support-annotations:26.1.0') {        force = true    }}

versionCode表示项目版本号,versionname表示项目的版本名,在后面会说到。
Buildype包用于指定生成安装文件的相关配置,通常包括deBUG和release,deBUG是测试版安装文件,release则为正式版安装文件,deBUG可以忽略不写的。
MinifyEnabled指定是否混淆,proguardfiles则用于指定混淆规则,后面有两个文件,一个是SDK目录下的,有所有项目的混淆规则,第二个文件是当前项目根目录下的,可以编写当前项目特有的混淆规则。
dependencIEs可以指定当前项目所有的依赖关系。通常一个AS项目一共有3种依赖方式:本地依赖、库依赖和远程依赖。本地依赖是对本地jar包或目录添加依赖,库依赖是对库模块添加依赖,远程依赖则可以对jcenter等仓库中的项目添加依赖。

日志工具

AndroID中的日志工具类是Log(androID.util.Log),提供了五个相关方法:

Log.v():打印最为繁琐、意义最小的日志,对应级别是verbose,级别最低Log.d():打印一些调试信息,有助于调试或者分析程序,对应级别是deBUG,比verbose高Log.i():打印一些比较重要的数据,对应级别是info,比deBUG高Log.w():打印一些警告信息,提示程序这里可能会有一些潜在风险,最好修复一下,对应级别是warn,比info高级Log.e(),打印错误信息,比如程序进入到catch中了,级别是error

测试一下,在MainAvtivity.java中的onCreate()方法中添加一行

Log.d("MainActivity","this is a dubug message");

就可以输入deBUG信息了,如下图所示,其中第一个参数是tag,一般写当前类名,便于过滤,第二个参数就是需要输出的信息。


为了方便使用日志工具,可以在每个类开头设置一个变量

private static final String TAG="...";

之后Log中的第一个参数直接TAG即可。
logcat可以使用过滤功能,AS默认提供了两个过滤器,也可以自定义。点击Edit Fliter Configuration,写好tag就行,点击OK,可以看到就只显示我们需要的log了。



等等,日志大概常用的就是这些,剩下的自己捉摸吧。

活动创建和使用

在此手动创建一个活动。
新建一个项目,不要选择Empty Activity,选择Add No Activity
进入后,右键app-java-com.example.k.androIDpractice_1 -> New -> Activity -> Empty Activity,同时取消Generate Layout file(自动创建布局文件)和Launcher Activity(设置为当前项目主活动)。



之后新建一个布局文件
右键app/res -> New -> Dictory,新建一个名为layout的文件夹,然后右键layout文件夹,New -> Layout resource file,xml名为first_layout,默认为linearLayout。
在xml中添加一个button,修改代码如下

<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    androID:orIEntation="vertical" androID:layout_wIDth="match_parent"    androID:layout_height="match_parent">    <button        androID:ID="@+ID/button_1"        androID:text="this is a button"        androID:layout_wIDth="match_parent"        androID:layout_height="wrap_content" /></linearLayout>

切换到design


之后需要在Activity中加载布局,在FirstActivity中添加如下一行
setContentVIEw(R.layout.first_layout);
设置布局,传入布局ID即可。
在AndroIDManifest.xml中注册Activity,其实AS已经帮我们注册了FirstActivity这个活动,代码如下

<?xml version="1.0" enCoding="utf-8"?><manifest xmlns:androID="http://schemas.androID.com/apk/res/androID"    package="com.example.k.androIDpractice_1">    <application        androID:allowBackup="true"        androID:icon="@mipmap/ic_launcher"        androID:label="@string/app_name"        androID:roundIcon="@mipmap/ic_launcher_round"        androID:supportsRtl="true"        androID:theme="@style/Apptheme">        <activity androID:name=".FirstActivity"></activity>    </application></manifest>

其中androID:name中应为com.example.k.androIDpractice_1.FirstActivity,因为外部有package,这里就简写了。
但是还是需要设置主活动,否则程序无法知道首先启动哪个Activity。
将Activity标签修改如下

<activity androID:name=".FirstActivity">            <intent-filter>                <action androID:name="androID.intent.action.MAIN"/>                <category androID:name="androID.intent.category.LAUNCHER"/>            </intent-filter>        </activity>

注意:如果没有指定一个Activity为主活动,程序还是可以运行的,只不过无法看到图标,一般是作为第三方服务提供的,比如支付宝的支付服务。
之后运行可以看到程序正常运行了。

Toast

Toast是一种很友好的提示方式,可以以短小的信息提示用户某些信息,在此对按钮进行监听以显示Toast。
修改MainActivity代码如下

button button=findVIEwByID(R.ID.button_1);        button.setonClickListener(new VIEw.OnClickListener() {            @OverrIDe            public voID onClick(VIEw v) {                Toast.makeText(FirstActivity.this,"this is a message",Toast.LENGTH_SHORT).show();            }        });
menu

设置菜单大概需要三步:

新建menu文件夹和编写main.xml中的item重写onCreateOptionsMenu(),设置我们写好的main.xml重写onoptionsItemSelected(),对菜单选项进行监听响应

在res文件夹下新建文件夹menu,右键menu文件夹,New -> Menuresourcefile,输入main点ok。在main.xml中添加如下代码

<?xml version="1.0" enCoding="utf-8"?><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>

这里创建了两个菜单选项Add和Remove指定其ID和显示内容。
需要重写onCreateOptionsMenu()方法,按ctrl+O重写方法,找到我们需要的,点击OK。


修改如下

@OverrIDe    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.main,menu);        return true;    }

其中getMenuInflater()方法获得MenuInflater对象,调用inflater()方法创建菜单。
之后需要定义菜单的响应事件,即监听菜单,需要重写onoptionsItemSelected()方法

public boolean onoptionsItemSelected(MenuItem item) {        switch (item.getItemID()){            case R.ID.Add_Item:                Toast.makeText(this,"这是Add",Toast.LENGTH_SHORT).show();                break;            case R.ID.Remove_Item:                Toast.makeText(this,"这是Remove",Toast.LENGTH_SHORT).show();                break;                default:break;        }        return true;    }

如果想结束一个Activity,在代码中可以直接通过finish()方法实现,即按返回键的功能

Activity跳转

在程序启动之后指挥进入到主活动,如何跳转到其他活动呢?需要使用intent。

显示Intent

创建一个Activity,叫SecondActivity,勾选generate不选launcher。
在activity_second.xml中添加button控件

<button        androID:ID="@+ID/button2"        androID:layout_height="wrap_content"        androID:layout_wIDth="match_parent"        androID:text="这是second activity"        />

修改FirstActivity中对button的监听,Intent一个重载是第一个参数为启动活动的上下文,第二个参数为需要启动的目标活动

protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.first_layout);        button button=findVIEwByID(R.ID.button_1);        button.setonClickListener(new VIEw.OnClickListener() {            @OverrIDe            public voID onClick(VIEw v) {                Intent intent=new Intent(FirstActivity.this,SecondActivity.class);                startActivity(intent);            }        });    }
隐式Intent

即为不明确启动某个Activity,而是指定一系列action或者category等信息,然后由系统找到合适的Activity启动。
修改AndroIDManifest.xml中的SecondActivity标签

<activity androID:name=".SecondActivity">            <intent-filter>                <action androID:name="con.example.k.androIDpractice_1.ACTION_START"/>                <category androID:name="androID.intent.category.DEFAulT"/>            </intent-filter>        </activity>

其中action指明了该活动可以响应的action,category具体包含了一些附加信息。
修改FirstActivity中的按钮监听

button.setonClickListener(new VIEw.OnClickListener() {            @OverrIDe            public voID onClick(VIEw v) {                Intent intent=new Intent("con.example.k.androIDpractice_1.ACTION_START");                startActivity(intent);            }        });

只有当action和category同时匹配的时候才能正确响应活动,由于此时的category是DEFAulT,因此不写的话会默认为DEFAulT。
每个Intent只可以指定一个action,但是可以指定多个category。
然后一个例子,启动浏览器,代码如下

button.setonClickListener(new VIEw.OnClickListener() {            @OverrIDe            public voID onClick(VIEw v) {                Intent intent=new Intent(Intent.ACTION_VIEW);                intent.setData(Uri.parse("http://www.baIDu.com"));                startActivity(intent);            }        });

如下所示,可以打开网页了,要注意网址一定要正确,比如必须要加http://,否则报错。其中INTENT.ACTION_VIEW是系统中的常量,值为androID.intent.action.VIEW。


通过setData()传入数据,标签中可以添加标签,更加精确配置响应什么类型的数据,主要可以配置如下内容

androID:sheme 数据的协议部分,如httpandroID:host 数据的主机部分,如www.baIDu.comandroID:port 数据的端口部分,一般跟在主机名后androID:path 用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容androID:mimeType 指定可处理数据的类型,允许使用通配符方式指定。

只有标签中指定的内容和Intent中携带的数据一致的时候才能正确响应。
一个简单示例,以响应http协议。新建Third_Activity,添加一个button3,修改AndroIDManifest.xml

<activity androID:name=".ThirdActivity">            <intent-filter>                <action androID:name="androID.intent.action.VIEW" />                <category androID:name="androID.intent.category.DEFAulT" />                <data androID:scheme="http"/>            </intent-filter>        </activity>

之后启动程序,点击按钮,可以看到已经识别到我们自定义的Activity了。

向下传递数据

大致思想就是先将数据存储到Intent中,再目标活动中取出数据即可。主要用到了putExtra()和getStringExtra()方法。

filename:FirstActivity.javabutton.setonClickListener(new VIEw.OnClickListener() {            @OverrIDe            public voID onClick(VIEw v) {                String data="this is a data string";                Intent intent=new Intent(FirstActivity.this,SecondActivity.class);                intent.putExtra("extra_data",data);                startActivity(intent);            }        });filename:SecondActivity.javasetContentVIEw(R.layout.activity_second);        Intent intent=getIntent();        String data=intent.getStringExtra("extra_data");        Toast.makeText(SecondActivity.this,data,Toast.LENGTH_SHORT);

可以看到由Toast生成了,说明成功了。

返回数据给上一级

大致步骤为三步:

调用startActivityForResult()启动Intent在待销毁活动中创建一个Intent,把数据放入其中,调用setResult()返回结果在上一级活动中重写onActivityResult()方法,从Intent中获取数据

需要使用到这么一个方法,startActivityForResult(),这个方法在销毁活动的时候会返回一个结果给上一级,有两个参数,第一个参数为Intent,第二个参数为一个请求码,保证其唯一即可。
在待销毁活动中创建一个Intent,不需要有参数,只是用来传递数据,通过putExtra把数据传入Intent中,调用setResult()返回Intent,有俩各个参数,第一个一般为RESulT_OK或者RESulT_CANCELED,之后调用finish()销毁。同时需要重写上一级活动中的onActivityResult()方法以得到数据,因为活动销毁后会调用上一级活动的这个方法。
修改代码

filename:FirstActivity.java...button.setonClickListener(new VIEw.OnClickListener() {            @OverrIDe            public voID onClick(VIEw v) {                String data="this is a data string";                Intent intent=new Intent(FirstActivity.this,SecondActivity.class);               startActivityForResult(intent,1);            }        });...protected voID onActivityResult(int requestCode, int resultCode, Intent data) {        switch (requestCode){            case 1:                if (resultCode==RESulT_OK){                    String string=data.getStringExtra("data_return");                    Toast.makeText(FirstActivity.this, string, Toast.LENGTH_SHORT).show();                }                break;        }    }filename:SecondActivity.java...button2.setonClickListener(new VIEw.OnClickListener() {            @OverrIDe            public voID onClick(VIEw v) {                Intent intent=new Intent();                intent.putExtra("data_return","hello,firstactivity");                setResult(RESulT_OK,intent);                finish();            }        });

可以看到成功获取到了数据。


由于可能会有多个Activity返回到同一个活动,因此需要在onActivityResult()中首先判断requestCode的值确定其来自于哪个活动(即为最开始的请求码),然后根据resultCode判断是否成功,之后从data中获取数据。
==============
如果是通过返回键返回的呢,重写待销毁活动的onBackpressed()方法即可。

活动生命周期

安卓中是通过任务来管理活动的,一个任务是一组存放在栈里的活动的集合,即返回栈。每当启动一个新的活动的时候,活动入栈处于栈顶位置,按下返回键或者调用finish()方法销毁一个方法的时候,栈顶的活动会出栈。系统总是显示栈顶的活动给用户。

活动状态

每个活动在生命周期最多有四个可能的活动状态

运行状态:处于返回栈栈顶的活动处于运行状态暂停状态:活动不处于栈顶但是仍然可见的时候,处于暂停状态,不是所有活动都必须占满全部屏幕,比如d出的对话框就只占据部分屏幕。停止状态:活动不处于栈顶且完全不可见的时候就处于停止状态,系统会保留相应状态和成员变量,但是不可靠,如果内存不够用的时候,这部分将被回收。销毁状态:当一个活动从栈顶移除后变成销毁状态,系统会优先回收这种状态的活动。活动的生命期

Activity类中定义了七个回调方法,覆盖了生命周期中的每一个环节

onCreate():在活动第一次被创建的时候调用,实现布局的加载、事件绑定等onStart():在活动由不可见变为可见的时候调用onResume():在活动准备好和用户进行交互的时候调用,此时活动一定处于栈顶,且处于运行状态onPause():在系统准备启动或恢复另一个活动时调用。一般在这里需要释放一些消耗cpu的资源,保存一些关键数据,要快,否则可能会影响新活动onStop():在活动完全不可见的时候调用。若启动新活动是类似对话框的活动,使用onPause(),onStop()不会执行onDestroy():在活动被销毁之前调用,之后活动会变为销毁状态onRestart():活动由停止状态变为运行状态的时候调用该方法,即活动被重新启动

还可以分为三种生存期

完整生存期:即onCreate()和onDestroy()之间所经历的是完整生命期,在onCreate()中进行初始化 *** 作,在onDestroy()中进行内存的释放可见生存期:在onStart()和onStop()之间所经历的是可见生命期。在这个期间活动都是可见的,即便某些无法交互的时候也是可见的。应在onStart()中完成资源的加载,onStop()中进行资源的释放前台生存期:在onResume()和onPause()之间所经历的是前台生存期。在这个期间活动总是处于运行状态,可以和用户进行交互


当一个活动进入停止状态的时候,可能会被回收。如在活动A上启动活动B,此时A进入停止状态,但是由于内存不足,A被回收,从活动B返回之后,仍会正常显示活动A,只不过不会调用onRestart()方法,而是会调用onCreate()方法。比如正在文本框中输入了文字,然后启动了另一个活动,返回之后,打的字没了,就是说这个活动被重新创建了。
Activity类中提供一个onSaveInstanceState()回调方法,可以保证在活动被回收之前一定会被调用
可以在此时临时保存数据避免数据消失的问题。重写该方法,参数是一个Bundle,Bundle提供了一系列方法用于保存数据,如putString(),putInt()等,这些方法都有两个参数,第一个是键值,第二个是保存的内容值。

protected voID onSaveInstanceState(Bundle outState){	super.onSaveInstanceState(outState);	String tempData="this is s temp data";	outState.putString("data_key",tempData);}

如何取出数据呢?onCreate()的参数也为Bundle,在该方法中从Bundle中取出数据

protected voID onCreate(Bundle savedInstancedState){	super.onCreate(saveInstanceState);	Log.d(TAG,"onCreate);	if (savedInstancedState != null){		String tempData=savedInstancedState.getString("data_key");		Log.d(TAG,tempData);	}}

Intent和Bundle有些类似,当然Intent可以和Bundle结合使用,把数据先保存到Bundle中,在把Bundle传入Intent中。

活动启动模式

在实际项目中需要根据需求合理设定不同的启动模式,一共有四种standard、singletop、singleTask和singleInstance。
通过AndroIDManifest.xml中中的androID:launchMode属性进行设置。

standard:每当standard模式启动的活动,不会在意是否已启动,即不会在意是否处于返回栈,每次启动都会创建一个新的活动,而且打开几个活动就需要按几次返回singletop:在启动的时候如果发现返回栈栈顶就是该活动,则不会创建新的活动,不管启动几次活动都只需要按一次返回,因为栈顶始终是该活动。但是如果该活动不处于栈顶位置,再次启动的话则仍会创建新的实例singleTask:使用singletop可以解决重复创建栈顶活动的问题,但是如果该活动不处于栈顶,则会创建很多活动。而singleTask模式会在返回栈中先检查是否存在待启动活动的实例,不存在的创建一个实例,如果存在则将其置为栈顶,并d出所有该活动之上的活动singleInstance:启动活动的时候会直接创建一个新的返回栈。假设有一个活动是需要共享的,如果使用前三种启动模式,均会创建新的实例,由于需要共享,因此不可能新建实例,所以使用单独的返回栈管理这个活动。(eg:设置second为singleInstance模式,在first启动second,在second启动third,则first和third处于同一个栈,second处于一个栈,此时栈顶活动为third,按返回会回到first而不是second,因为first和third处于同一个栈,再次按返回之后才会回到second,因为该栈已空,再次返回后会退出活动的应用找到界面对应的活动

在实际中可能并不确定哪个界面对应的是哪个Activity。这时候需要进行一点修改就好了。
新建一个名为BaseActivity的普通java class,不需要注册为Activity,编写代码如下

public class BaseActivity extends AppCompatActivity{	protected voID onCreate(Bundle savedInstanceState){		super.onCreate(savedInstanceState);		Log.d("BaseActivity",getClass().getSimplename());	}}

之后将项目中Activity类中继承的AppCompatActivity改为继承BaseActivity,此时项目中的Activity类依然继承AppCompatActivity,因为BaseActivity继承于AppCompatActivity。
之后再运行程序,每当启动一个活动日志就会打印出该活动对应的类名。

快速直接退出程序

当启动多个程序的时候需要直接退出程序,直接按返回键的话可能需要多次,要想一次退出的话可以使用一个集合作为Activity管理器来保存当前所有活动进行处理。

public class ActivityCollector{	public static List<Activity> acticitIEs=new ArrayList<>();	public static voID addActivity(Activity activity){		acticitIEs.add(activity);	}	public static voID removeActivity(Activity activity){		activitIEs.remove(activity);	}	public static voID finishAll(){		for (Activity activity:activitIEs){			if (!activity.isFinishing()){				activity.finish();			}		}		activitIEs.clear();	}}

之后需要修改一下上面的BaseActivity代码

public class BaseActivity extends AppCompatActivity{	protected voID onCreate(Bundle savedInstanceState){		super.onCreate(savedInstanceState);		Log.d("BaseActivity",getClass().getSimplename());		ActivityCollector.addActivity(this);	}	protected voID onDestroy(){		super.onDestroy();		ActivityCollector.removeActivity(this);	}}

之后如果需要一次退出程序的话只需要调用ActivityCollector.finishAll()方法即可。

启动程序的好技巧

在启动另一个活动的时候,需要传递参数的话,如果不是我们写的活动,不太容易知道都需要什么参数之类的,因此修改一下代码,结构就会很清晰明了。

filename:SecondActivity.javapublic class SecondActivity extends BaseAvtivity{	public static voID actionStart(Context context,String Data1,String Data2){		Intent intent=new Intent(context,SecondActivity.class);		intent.putExtra("param1",Data1);		intent.putExtra("param2",Data2);		context.startActivity(intent);	}	...}

然后

filename:FirstActivity.javapublic voID onClick(VIEw v){	SecondActivity.actionActivity(FirstActivity.this,"123","456");}

这样就很清楚了。

balabala

安卓只写过几个小程序,虽然现在只把活动看完了,但是感觉真的认识了不少东西和方法,比如生命周期生存期,之前只是知道现象但是具体不知道是什么,现在有了一个系统的总结。几句这样,明天继续。

OK,THANKS FOR READING.BYE BYE~点赞收藏分享文章举报

BluePROT发布了15 篇原创文章 · 获赞 5 · 访问量 5188私信 关注 总结

以上是内存溢出为你收集整理的Android开发 入门篇(一)全部内容,希望文章能够帮你解决Android开发 入门篇(一)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1068414.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-26
下一篇2022-05-26

发表评论

登录后才能评论

评论列表(0条)

    保存