
date: 2020-01-09 12:56:40
有些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.gradleAS中是用gradle构建项目的,gradle是一个先进的项目构建工具。使用基于Groovy的领域特定语言(DSL)声明项目配置,摒弃了基于XML的繁琐配置。
项目中有两个build.gradle文件,一个是外层的,一个是内层app目录下的。
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 gradleapply 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。
修改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属性进行设置。
在实际中可能并不确定哪个界面对应的是哪个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开发 入门篇(一)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)