activity的管理:
复习:定义一个activity
—— 创建一个Activity子类
——重写Activity中的onCreate方法
—— 在AndroidManifest.xml中的Activity进行注册
启动一个Activity
——创建Intent意图对象(可以理解成一个封装对象
)
——调用setClass设置要启动哪个Activity
——调用startActivity进行跳转
BackStack回退栈
1、先进后出 2、方便记录后维护
Menu分类:
选项菜单(OptionMenu)
上下文菜单(ContextMenu)
弹出菜单(PopupMenu)
OptionMenu:
showAsAction属性值:always:直接在标题显示
never:不显示
withText:控制图标贺文本一起显示
ifRoot:有空间就显示
//创建OptionMenu
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//加载资源文件
getMenuInflater ().inflate ( R.menu.option,menu );
return true;
}
//OptionMenu添加事件方法
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId ()){
case R.id.menu1:
Toast.makeText ( this, "保存", Toast.LENGTH_SHORT ).show ();
break;
case R.id.menu2:
Toast.makeText ( this, "设置", Toast.LENGTH_SHORT ).show ();
break;
}
return super.onOptionsItemSelected ( item );
}
ContextMenu:
长按某个view不放,就会在屏幕中间弹出ContextMeun
//contextMenu:演示ContextMenu
//4、为按钮设置上下操作模式,要进入上下操作模式就要先创建 ActionMode.Callback对象
//①实现ActionMode CallBack
//②在view的长按事件中去启动上下文操作模式
//先创建 ActionMode.Callback对象
ActionMode.Callback cb=new ActionMode.Callback () {
//创建,在启动上下文操作模式(startActionMode(Callback))是调用
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
Log.i ( "TAG","创建" );
getMenuInflater ().inflate ( R.menu.contextmenu,menu );
return true;
}
//在创建方法后进行调用
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
Log.i ( "TAG","准备" );
return false;
}
//单击按钮时
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId ()){
case R.id.up_name:
Toast.makeText ( mode1_activity.this, "重命名", Toast.LENGTH_SHORT ).show ();
break;
case R.id.del:
Toast.makeText ( mode1_activity.this, "删除", Toast.LENGTH_SHORT ).show ();
break;
}
return true;
}
//上下文操作模式结束时被调用
@Override
public void onDestroyActionMode(ActionMode mode) {
Log.i ( "TAG","结束" );
}
};
//调用
findViewById ( R.id.contextMenu ).setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
startActionMode ( cb );
}
} );
//如果不进入上下本模式
//1、注册
registerForContextMenu ( findViewById ( R.id.contextMenu ) );
//2、创建 覆盖
//2、创建 覆盖onCreateContextMenu
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
getMenuInflater ().inflate ( R.menu.contextmenu,menu );//
super.onCreateContextMenu ( menu, v, menuInfo );
}
//3、菜单项的操作onContextItemSelected
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
switch (item.getItemId ()){
case R.id.up_name:
Toast.makeText ( this, "重命名", Toast.LENGTH_SHORT ).show ();
break;
case R.id.del:
Toast.makeText ( this, "删除", Toast.LENGTH_SHORT ).show ();
break;
}
return super.onContextItemSelected ( item );
}
PopupMenu:
按一下某个view,一般会在下方弹出
//popupMenu:演示PopupMenu
final Button button=findViewById ( R.id.popupMenu );
button.setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
// ①实例化PopupMenu对象(参数2:被锚定的view)
PopupMenu popupMenu=new PopupMenu ( mode1_activity.this, button);
// ②加载菜单资源:利用MenuInflater将Menu资源加载到PopupMenu.getMenu(),所返回的Menu对象中
//将R.meun.contextmenu对于的菜单资源加载到弹出式菜单中
popupMenu.getMenuInflater ().inflate ( R.menu.popupmenu,popupMenu.getMenu () );
// ③为PopupMenu设置点击监听器
popupMenu.setOnMenuItemClickListener ( new PopupMenu.OnMenuItemClickListener () {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId ()){
case R.id.copy:
Toast.makeText ( mode1_activity.this, "复制", Toast.LENGTH_SHORT ).show ();
break;
case R.id.del1:
Toast.makeText ( mode1_activity.this, "删除", Toast.LENGTH_SHORT ).show ();
break;
}
return true;
}
} );
// ④千万不要忘show
popupMenu.show ();
}
} );
java编写menu:
对话框
1、普通对话框(一):
利用AlterDialog中的构建器(Builder)来完成。
通过方法有:setTitle、setMessage、create、show
三个事件:
——setPositiveButton:确定
——setNegativeButton:否
——setNeutralButton:取消
private void showdialog1() {
/*
* AlertDialog
* AlerDialog的构造方法是被修饰为protected
* 因此包外是无法使用的,所以我们利用构建器(Builder)
* */
AlertDialog.Builder builder=new AlertDialog.Builder ( this );
// 设置对话框标题
builder.setTitle ( "提示" );
// 设置内容
builder.setMessage ( "你是否要退出程序!" );
// 设置按钮
builder.setPositiveButton ( "确定", new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
activity_Dialog.this.finish ();
}
} );
builder.setNegativeButton ("取消",null );
// builder.setNeutralButton ( );
// builder.create ();
builder.show ();
}
2、普通对话框(二):
用到几个常量:BUTTON_POSITIVE、BUTTON_NEGATIVE、BUTTON_NEUTRAL
// 打分式对话框
private void showdialog2() {
AlertDialog dialog=new AlertDialog.Builder (this).create ();
dialog.setTitle ( "评价" );
dialog.setMessage ( "请为本次服务打分!" );
//BUTTON_POSITIVE:常量
dialog.setButton ( DialogInterface.BUTTON_POSITIVE, "5分", new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText ( activity_Dialog.this, "您选择了5分", Toast.LENGTH_SHORT ).show ();
}
} );
dialog.setButton ( DialogInterface.BUTTON_NEGATIVE, "3分", new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText ( activity_Dialog.this, "您选择了3分", Toast.LENGTH_SHORT ).show ();
}
} );
dialog.setButton ( DialogInterface.BUTTON_NEUTRAL, "1分", new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText ( activity_Dialog.this, "您选择了1分", Toast.LENGTH_SHORT ).show ();
}
} );
dialog.show ();
}
3、列表对话框:
有一个方法:setItems
// 列表对话框
private void showdialog3() {
final String[] strings={"我是1","我是2","我是3","我是4"};
AlertDialog.Builder dialog=new AlertDialog.Builder ( this );
dialog.setTitle ( "请选择" );
dialog.setItems ( strings, new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
/*
which:strings的索引从0开始
* */
Toast.makeText ( activity_Dialog.this, strings[which], Toast.LENGTH_SHORT ).show ();
}
} );
dialog.show ();
}
4、单选对话框:
方法:setSingleChoiceItems
// 单选对话框
int s = 0;
private void showdialog4() {
final String[] strings={"赵丽颖","蓝洁瑛","范冰冰","王源","唐嫣","杨幂"};
AlertDialog.Builder dialog=new AlertDialog.Builder ( this );
dialog.setTitle ( "你喜欢谁?" );
/*
* strings:数组
* 0:是默认选中的
* */
dialog.setSingleChoiceItems ( strings, 0, new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
s =which;
}
} );
dialog.setPositiveButton ( "确定", new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText ( activity_Dialog.this, strings[str[0]],Toast.LENGTH_SHORT ).show ();
}
} );
dialog.show ();
}
5、多选对话框:
方法:setMultiChoiceItems
// 多选对话框
private void showdialog5() {
final String[] strings={"赵丽颖","蓝洁瑛","范冰冰","王源","唐嫣","杨幂"};
final boolean[] start={true,true,false,false,false,false};
AlertDialog.Builder dialog=new AlertDialog.Builder ( this );
dialog.setTitle ( "你选择那些!" );
dialog.setMultiChoiceItems ( strings, start, new DialogInterface.OnMultiChoiceClickListener () {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
/*
* dialog:对象控件
* which:索引
* isChecked:状态
* 当改变复选框状态时触发
* */
start[which]=isChecked;
}
} );
dialog.setPositiveButton ( "确定", new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
String mes="";
for (int i=0;i<strings.length;i++) {
if (start[i]){
mes+=strings[i]+"、";
}
}
Toast.makeText ( activity_Dialog.this, mes, Toast.LENGTH_SHORT ).show ();
}
} );
dialog.show ();
}
6、等待对话框(progressDialog):
方法:setCancelable
// 等待对话框
private void showdialog6() {
ProgressDialog progressDialog=new ProgressDialog ( this );
progressDialog.setTitle ( "请等待" );
progressDialog.setMessage ( "正在加载..." );
progressDialog.setCancelable ( false );//默认为true(是否可返回)
progressDialog.show ();
progressDialog.dismiss ();//关闭对话框
}
7、进度条对话框
方法:setIndeterminate、setProgressStyle(ProgressDialog.STYLE.HORIZONTAL)
// 进度条对话框
private void showdialog7() {
final ProgressDialog progressDialog=new ProgressDialog ( this );
progressDialog.setTitle ( "下载中" );
progressDialog.setMessage ( "正在加载..." );
progressDialog.setIndeterminate ( false );//默认:false,设置为模糊的
// 设置样式
progressDialog.setProgressStyle ( ProgressDialog.STYLE_HORIZONTAL );
progressDialog.show ();
// progressDialog.setProgress ( 30 );
new Thread ( ){
@Override
public void run() {
for (int i=0;i<=100;i++){
progressDialog.setProgress ( i );
try {
Thread.sleep ( 40 );
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
progressDialog.dismiss ();
}
}.start ();
}
8、输入对话框
方法:setView
// 输入对话框
private void showdialog8() {
final EditText edit=new EditText ( this);
AlertDialog.Builder dialog=new AlertDialog.Builder ( this );
dialog.setTitle ( "输入对话框" );
dialog.setView ( edit);//这里可以用布局文件
dialog.setPositiveButton ( "确定", new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText ( activity_Dialog.this, "输入:"+edit.getText ().toString (), Toast.LENGTH_SHORT ).show ();
}
} );
dialog.show ();
}
9、自定义对话框
/*
*自定义对话框
* 1、自定义一个类,继承Dialog类
* 2、创建一个样式(style),不显示标题栏 不显示背景
* 3、绑定布局,添加事件
* 4、调用并显示
* */
//自定义一个类,继承Dialog类
public class Mydialog extends Dialog {
public Mydialog(@NonNull Context context) {
super ( context, R.style.Mydialog );
setContentView ( R.layout.my_dialog );
Button confirm=findViewById ( R.id.confirm );
Button cancel=findViewById ( R.id.cancel );
confirm.setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
System.exit ( 0 );//退出程序
}
} );
cancel.setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
dismiss ();
}
} );
}
}
//调用并显示
Mydialog mydialog=new Mydialog ( this );//自定义的类
mydialog.setCancelable ( false );//默认为true(是否可退出对话框
mydialog.show ();
//创建一个样式(style),不显示标题栏 不显示背景
<!--自定义一种样式-->
<style name="Mydialog" parent="android:style/Theme.Dialog">
<!-- Customize your theme here. -->
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
布局:
<?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:background="#A29EA9"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="提示"
android:textSize="30dp"
android:textStyle="bold"
android:textColor="#fff"
android:gravity="center"/>
<TextView
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#ffffff"/>
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="你确定要执行吗?"
android:textColor="#fff"
android:gravity="center"
android:textSize="20dp"/>
<LinearLayout
android:layout_marginHorizontal="80dp"
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/confirm"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="确定"/>
<Button
android:id="@+id/cancel"
android:layout_marginLeft="10dp"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="取消"/>
</LinearLayout>
</LinearLayout>
10、比较特殊的对话框
如果你想做成这样:
可以利用:ArrayAdapter
/*
* 1、创建一个xml布局做资源
* 2、添加ArrayAdapter
* 3、setAdapter
* */
private void showdialog10() {
final String[] strings={"Python","Java","C","C#","PHP","JavaScript","Object-C","Ruby"};
ArrayAdapter adapter=new ArrayAdapter (this,R.layout.mydialog2,R.id.text1,strings );//R.id.text1:指定控件
AlertDialog.Builder dialog=new AlertDialog.Builder ( this );
dialog.setTitle ( "请选择" );
dialog.setAdapter ( adapter, new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText ( activity_Dialog.this, strings[which], Toast.LENGTH_SHORT ).show ();
}
} );
dialog.show ();
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingVertical="10dp"
android:gravity="center|left">
<ImageView
android:paddingLeft="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher_round"/>
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:textSize="30dp"
android:textStyle="bold"
android:text="Java"/>
</LinearLayout>
Activity生命周期详解
1、onCreate——创建(怀孕)
2、onStart——出生
3、onResume——可以交互(可点击可操作了)(可用了)
4、onPause——暂停了(可能生病了)
5、onStop——停止(老去)
6、onDestroy——被销毁了
7、onRestart——被销毁又活了(回光返照)
另外还有两个较重要的方法:
8、onBackPressed——当按返回时被触发
9、onSaveInstanceState——当程序被杀掉时执行触发
Activity之间的数据传递:
装在Intent对象中:
可以传:
——基本类型
——bundle对象
——序列化
put…
get…
如:
//存数据
Intent intent = new Intent ( life_activity.this, Main1_zhuye.class );
Bundle bundle=new Bundle ();
bundle.putString ( LIFE_DATA,"命名" );
intent.putExtra ( "bundle",bundle );
startActivity ( intent );
//取数据
if (getIntent ()!=null){
Bundle bundle= getIntent ().getBundleExtra ( "bundle" );
text.setText (bundle.getString ( life_activity.LIFE_DATA ) );
}
当一个activity调用别一个activity,调用的activity销毁了,想返回数据到第一个activity:
//调用的方式要换成startActivityForResult
Intent intent2=new Intent (life_activity2.this,Main1.class);
Bundle bundle=new Bundle ();
bundle.putString ( "key","第一个页面" );
intent2.putExtra ( "key1", bundle);
startActivityForResult (intent2 ,777 );
//想返回数据可以在第二个页面加setResult
@Override
protected void onDestroy() {
super.onDestroy ();
Intent intent=new Intent ();
intent.putExtra ( "kkk","我是第二个页面关闭后返回的数据" );
setResult ( 111,intent);
finish ();
}
//第二个页面销毁后会回调第一个页面的onActivityResult方法,就可以接受返回的数据了
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult ( requestCode, resultCode, data );
if (requestCode==777&&resultCode==111){
String srt=data.getStringExtra ( "kkk" );
text.setText ( srt );
}
}
Fragment:
一、Fragment与Activity的区别:
1、Fragment是到Android3.0以后出现的
2、一个Activity可以运行多个Fragment
3、Fragment不能脱离Activity而存在
4、Activity是屏幕的主体,而Fragment是Activity的一个组成员元素
Fragment的生命周期:
二、两种加载方法:
(一)、静态加载:xml
<fragment
android:id="@+id/fragment1"
android:layout_width="200dp"
android:layout_height="200dp"
android:name="com.example.myapplication.Fragment.myfragment"/>
(二)、动态加载:
getSupportFragmentManager ().
beginTransaction ().
replace ( R.id.line1, new myfragment_shez ()).
commit ();
切换:Add、Remove、Replace
三、传值:
(一)、Activity向Fragment传值:
在Fragment中加一个静态方法,并返回Fragment的实例,利用setArguments方法传值
public static final String KEY = "key";
public static myfragment_insert newfragemt_insert(String title) {
myfragment_insert insertFragment=new myfragment_insert ();
Bundle bundle=new Bundle ();
bundle.putString ( KEY,title );
insertFragment.setArguments ( bundle );
return insertFragment;
}
//取数据
if (getArguments ()!=null){
tilte = getArguments ().getString ( KEY );
}
(二)、Activity向Fragment传值:利用接口回调
//1、fragment中写一个接口
//2、activity中实现接口,并调用setonTitleclickListener方法
//接口写值方法
public void setonTitleclickListener(onTitleclickListener onTitleclickListener){
monTitleclickListener=onTitleclickListener;
}
private onTitleclickListener monTitleclickListener;//创建接口变量
//定义接口
public interface onTitleclickListener{
Void onclick(String title);
}
//2、activity中实现接口,并调用setonTitleclickListener方法(onTitleclickListener是我在myfragment_insert这个类中的定义的接口)
public class Activity_fragment extends AppCompatActivity implements myfragment_insert.onTitleclickListener {
@Override
public Void onclick(String title) {
setTitle ( title );
return null;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
myfragment_insert activity_fragment = myfragment_insert.newfragemt_insert ( "Activity_fragment" );
getSupportFragmentManager ().beginTransaction ().replace ( R.id.line1, activity_fragment ).commit ();
activity_fragment.setonTitleclickListener ( this );//调用setonTitleclickListener
}
}
二、Fragment的管理:
(一)、FragmentManager API
——FragmentManager用来管理Activity中的Fragmet
——findFragmentByid(通过id查找Activity中的Fragment
——findFragmentByTag(通过字符串查找Activity中的Fragment
——popBackStack(模拟用户的点击Back键的操作
——addOnBackStackChangedListener()添加后台栈改变监听器
(二)、FragmentTTransaction API
——add()向容器中添加一个Fragment
——remove()删除一个Fragment
——replace()将容器中的Fragment替换成新的Fragment
——hide()隐藏已存在的Fragment
——show()显示此前隐藏的Fragment
——addToBackStack()将事务添加到后台栈
——commit()提交事务,将改变应用到Activity
(三)、系统提供的Fragment:
系统提供了几个其他的Fragment类开发者可以继承:
1、DialogFragment —— 显示一个悬浮对话框
2、ListFragment —— 显示一个由adapter管理的项目列表
悬浮对话框:
//DialogFragment 的使用
public static class Mydialog extends DialogFragment {
private String title;
public static Mydialog newDialogFragment(String title){
Mydialog mydialog=new Mydialog ();
Bundle bundle=new Bundle ();
bundle.putString ( "title",title );
mydialog.setArguments ( bundle );
return mydialog;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
title = getArguments ().getString ( "title" );
Dialog dialog = new AlertDialog.Builder ( getActivity () )
.setTitle ( title )
.setPositiveButton ( "确定", new DialogInterface.OnClickListener () {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText ( getActivity (), "ok", Toast.LENGTH_SHORT ).show ();
}
} )
.setNegativeButton ( "取消",null )
.create ();
return dialog;
}
}
ListFragment :
public static class mylistfragment extends ListFragment{
private String[] data;
public static mylistfragment newmylistfragment(String[] data){
mylistfragment mylistfragment=new mylistfragment ();
Bundle bundle=new Bundle ();
bundle.putStringArray ( "data",data );
mylistfragment.setArguments ( bundle );
return mylistfragment;
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach ( context );
data=getArguments ().getStringArray ( "data" );
setListAdapter ( new ArrayAdapter<String> (
getActivity (),
android.R.layout.simple_expandable_list_item_1,
android.R.id.text1,
data
) );
}
@Override
public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) {
Toast.makeText ( getActivity (), data[position], Toast.LENGTH_SHORT ).show ();
super.onListItemClick ( l, v, position, id );
}
}```
# 抽屉(DrawerLayout与ScrolView):
一、DrawerLayout
//DrawerLayout
<?xml version="1.0" encoding="utf-8"?><androidx.drawerlayout.widget.DrawerLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=".DrawerLayout.drawerLayout"
android:orientation=“vertical”
android:id="@+id/drawer">
</androidx.drawerlayout.widget.DrawerLayout>
(二)、ScrolView
——ScrollView和HorzontalScrollView是为控件或者布局添加滚动条
——ScrollView和HorzontalScrollView只能有一个子控件
——SrollView用于设置垂直滚动条,HorizontalScrollView用于设置水平滚动条
注意:srrolView里面只能有一个控件或布局
# 消息处理机制
为什么要使用线程:
——当主线程执行的操作时间过长,就无法执行其他操作。消息队列中的消息无法处理,UI界面就不会更新,用户事件也不会处理。
——如果主线程执行一个操作超过5秒,Android可能会弹出一个应用程序没有响应的对话框,你的Activity可能会被杀掉。

——常见的耗时操作如下:
网络连接和网络疏忽的获取
对存储器的读写
大量的数据计算
一、消息队列(MessageQueue)
——Android采用一种复杂的Message Queue机制保证线程间通信
——Message Queue是一个信息队列,用来存放通过Handler发布的信息。Android在第一次启动程序时会默认为UI线程创建一个关联的消息队列,用来管理程序的组件,如Activity,Service,Broatcast Receiver等
——可以在工作线程中城建Handler与UI线程通信。

二、Handler的消息传递机制:
——工作线程可以通过Handler对象和主线程通讯
——Handler对象的所有工作将在主线程中执行
——Handler类需要实现handleMessage()方法,来处理信息队列中取出的Message对象。what值对应
——handlerMessage()方法由主线程调用,可以在需要的时候更新UI界面。但是必须确保次方法快速完成,因为其他UI操作会等待它完成才能执行。
——可以在Message中附加不同的参数

注意:子线程中是不可操作UI控件的
(一)、Handler处理
在这里插入代码片
三、xml解析:
//PullParser解析xml文件
public List<String> getXmlPullParser(Resources res,int id) throws XmlPullParserException, IOException {
List<String> listdata = null;
XmlPullParser xml=res.getXml ( id );
int eventype=xml.getEventType ();
while (eventype!=XmlPullParser.END_DOCUMENT){
String gen=null;
switch (eventype){
case XmlPullParser.START_DOCUMENT://文档开始
// Log.i ( "tag","START_DOCUMENT" );
listdata=new ArrayList<> ();
break;
case XmlPullParser.END_DOCUMENT://文档结束
//Log.i ( "tag","END_DOCUMENT" );
break;
case XmlPullParser.START_TAG://标记(标签)开始
gen=xml.getName ();//取属性名
if (gen.equals ( "Button" )){
String value=xml.getAttributeValue ( 0 );//取属性的值
listdata.add ( value );
Log.i ( "tag","START_TAG:"+gen +"="+value);
}
break;
case XmlPullParser.END_TAG://标记(标签)结束
gen=xml.getName ();
Log.i ( "tag","END_TAG:"+gen );
break;
}
eventype=xml.next ();//下一个
}
return listdata;
}
四、josn解析:
一、JSON的概念:
——JSON(javascript object notation),是一种轻量级的数据存储贺交换格式
——它是完全独立于语言的文本格式
——JSON易于阅读、编写,也易于机器解析贺生成。
二、JSON基本格式:
——键值对对象格式:用“{}”包围
——数组格式:用“[]” 包围。
/*
* JSONObject:{}
* JSONArray:数组([])
* */
如:String data="{"name":"Tom"}";
/*
* json数据:
{
“data”: [
{
“id”: 12,
“url”: “”,
“br”: 0,
“size”: 0,
“md5”: null,
“code”: 404,
“expi”: 0,
“type”: null,
“gain”: 0,
“fee”: 0,
“uf”: null,
“payed”: 0,
“flag”: 0,
“canExtend”: false,
“freeTrialInfo”: null,
“level”: null,
“encodeType”: null
}
],
“code”: 200
}
* */
public void JOSN_string(String str) throws JSONException {
JSONObject object=new JSONObject (str);//取到json对象
JSONArray object1 = object.getJSONArray ( “data” );//取到json数组
for (int i=0;i<object1.length ();i++){
JSONObject data3 = object1.getJSONObject ( 0 );//取数组第一个
int id=data3.getInt ( “id” );//去属性值(键值对)
String url=data3.getString ( “url” );
int br=data3.getInt ( “br” );
int size=data3.getInt ( “size” );
String md5=data3.getString ( “md5” );
int code=data3.getInt ( “code” );
int expi=data3.getInt ( “expi” );
String type=data3.getString ( “type” );
int gain=data3.getInt ( “gain” );
int fee=data3.getInt ( “fee” );
String uf=data3.getString ( “uf” );
int payed=data3.getInt ( “payed” );
int flag=data3.getInt ( “flag” );
boolean canExtend=data3.getBoolean ( “canExtend” );
String freeTrialInfo=data3.getString ( “freeTrialInfo” );
String level=data3.getString ( “level” );
String encodeType=data3.getString ( “encodeType” );
Log.i ( “data”,id+","+url+","+br+","+size+","+md5+","+code+","+expi+","+type+
“,”+gain+","+fee+","+uf+","+payed+","+flag+","+canExtend+","+canExtend+","+freeTrialInfo
+","+level+","+encodeType
);
}
String object2 = object.getString ( “code” );
}
## Adapter适配器:
分类:ArrayAdapter、SimpleAdapter、BaseAdapter、ExpandableListAdapter
1、ArrayAdapter:
//简单适配器(ArrayAdapter)
private void adapter1() {
final String[] data = {"AA", "BB", "CC", "AA", "BB", "CC", "AA", "BB", "CC"};
ArrayAdapter<String> adapter = new ArrayAdapter<> (
this,//上下文
android.R.layout.simple_list_item_1,//布局
android.R.id.text1,//数据显示控件id
data//数据源
);
//事件
listview.setOnItemClickListener ( new AdapterView.OnItemClickListener () {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
/*
* parent:适配器
* view:控件
* position:索引
* */
Toast.makeText ( Activity_adapte.this, data[position], Toast.LENGTH_SHORT ).show ();
}
} );
listview.setAdapter ( adapter );//绑定适配器
}
2、SimpleAdapter:
//适配器(SimpleAdapter)
private void adapter2() {
List<Map<String, Object>> listdata = new ArrayList ();
Map<String, Object> map = new HashMap<> ();
map.put ( “name”, “张三” );
map.put ( “age”, “18” );
listdata.add ( map );
Map<String, Object> map1 = new HashMap<> ();
map1.put ( “name”, “李四” );
map1.put ( “age”, “28” );
listdata.add ( map1 );
Map<String, Object> map3 = new HashMap<> ();
map3.put ( “name”, “蔡徐坤” );
map3.put ( “age”, “22” );
listdata.add ( map3 );
SimpleAdapter adapter1 = new SimpleAdapter (
this,//上下文
listdata,//数据源
R.layout.simple_1,//布局
new String[]{“name”, “age”},
new int[]{R.id.text1, R.id.text2}
);
listview.setAdapter ( adapter1 );
}
3、BaseAdapter :
//自定义的适配器
public class Myadapte extends BaseAdapter {
int[] img={
R.mipmap.list_my,
R.mipmap.list_my_menu,
R.mipmap.list_pwd,
R.mipmap.list_safe_center,
R.mipmap.list_save,
R.mipmap.list_service
};
String[] name={
"a","b","c","d","e","f"
};
//源数据的个数
@Override
public int getCount() {
return img.length;
}
//索引项
@Override
public Object getItem(int position) {
return position;
}
//索引项
@Override
public long getItemId(int position) {
return position;
}
//项显示的view
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view;
viewHolder holder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from ( Activity_adapte.this );//布局管理器
view = inflater.inflate ( R.layout.simple_2, parent, false );//创建视图
holder=new viewHolder ( view );//将视图交由viewHolder管理
} else {
view = convertView;
holder= (viewHolder) convertView.getTag ();
}
ImageView imgage = holder.getview1 ( );
TextView age = holder.getview2 ( );
Button but1=holder.getview3 ();
imgage.setImageResource ( img[position] );
age.setText (name[position] );
but1.setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
Toast.makeText ( Activity_adapte.this, "点击了"+name[position], Toast.LENGTH_SHORT ).show ();
}
} );
return view;
}
//管理控件的类,为了节约内存
class viewHolder {
private View view;
private ImageView img;
private TextView name;
private Button but1;
public viewHolder(View view) {
this.view = view;
}
public ImageView getview1() {
if (img == null) {
img = view.findViewById ( R.id.img );
}
return img;
}
public TextView getview2() {
if (name == null) {
name = view.findViewById ( R.id.text );
}
return name;
}
public Button getview3() {
if (but1 == null) {
but1 = view.findViewById ( R.id.but1 );
}
return but1;
}
}
}
## 自定义控件:
——按类型划分,自定义View的实现方式可分为三种:
自绘控件
组合控件
继承控件
一、自绘控件:
——在View上所展现的内容全部都是绘制出来的
——绘制的代码是写在onDraw()方法中的
——自定义的View在界面上显示,只需要像使用普通的控件一样来使用自定义View就可以了。
package com.example.myapplication.my_control;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.example.myapplication.R;
/*
-
自绘控件
-
/
public class MyView extends View implements Runnable{
private Paint mpaint;//画笔
private Bitmap mbitmap;
private int x;
private boolean flag;
public MyView(Context context) {
super ( context );
inti();
}
/- 一代吗的方式动态加View到容器时使用
- /
public MyView(Context context, @Nullable AttributeSet attrs) {
super ( context, attrs );
inti();
}
/ - 当以XML布局文件的方式使用时,自动调用
- */
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super ( context, attrs, defStyleAttr );
inti();
}
private void inti() {
mpaint=new Paint ();
mpaint.setColor ( Color.RED );//设置画笔颜色
mpaint.setStyle ( Paint.Style.STROKE );//设置画笔样式
mpaint.setStrokeWidth ( 3 );//设置画笔线条的宽度
mbitmap= BitmapFactory.decodeResource ( getResources (), R.mipmap.find_hot_city );//取得位图
mbitmap=mbitmap.createScaledBitmap ( mbitmap,1600,1400,true );//创建一个缩放的Bitmap对象
}
public void setFlag(boolean start){
flag=start;
}
/*-
canvas:画布
-
mpaint:画笔
-
*/
@Override
protected void onDraw(Canvas canvas) {//canvas.drawCircle ( 50,50,50, mpaint);//绘制圆
//canvas.drawRect ( 10,100,10,100,mpaint );//绘制矩形
// canvas.drawBitmap ( mbitmap,10,10,null );//绘制图片
moveBackground(canvas);
super.onDraw ( canvas );
}
private void moveBackground(Canvas canvas){
x-=5;
int x2=mbitmap.getWidth ()-(-x);
if (x2<=0){
x=0;
canvas.drawBitmap ( mbitmap,x,10,null );
}else {
canvas.drawBitmap ( mbitmap,x,10,null );
canvas.drawBitmap ( mbitmap,x2,10,null );
}
}
@Override
public void run() {
while (flag){
//线程中不可以直接调用onDraw方法
postInvalidate ();//在线程中要求View重新呈现
}
}
}
二、自定义布局
1、用xml布局文件自定义布局
//自定义布局(用了一个xml布局文件)
public class My_layout extends LinearLayout {
private TextView text;
private Button but1;
private Context context;
public My_layout(Context context) {
super ( context );
this.context=context;
View view=inti();
}
public My_layout(Context context, @Nullable AttributeSet attrs) {
super ( context, attrs );
this.context=context;
View view=inti();
this.addView ( view );
}
public View inti() {
LayoutInflater inflater=LayoutInflater.from ( context );
View view=inflater.inflate ( R.layout.ling_layout,null );
return view;
}
}
//xml文件
<?xml version="1.0" encoding="utf-8"?>
//使用
setContentView ( new My_layout );
2、纯java代码自定义布局
public class My_layout2 extends LinearLayout {
private TextView text;
private Button but1;
private Context context;
public My_layout2(Context context) {
super ( context );
this.context=context;
inti();
}
public My_layout2(Context context, @Nullable AttributeSet attrs) {
super ( context, attrs );
this.context=context;
inti();
}
//要使用控件必须先new出来
public void inti() {
text=new TextView ( context );
but1=new Button ( context );
LayoutParams params=new LayoutParams (280,LayoutParams.WRAP_CONTENT,1 );
this.setOrientation ( LinearLayout.HORIZONTAL );//设置布局方向
this.setBackgroundColor ( Color.RED );
this.setLayoutParams ( params );
this.addView ( but1 );
this.addView ( text );
}
}
//使用
setContentView ( new My_layout2 );
三、 继承控件
——并不需要自己重头去实现一个控件,只需要去继承要给现有的控件,然后再这个控件上增加一些新的功能,就可以形成一个自定义的控件。
——继承控件的特点就是不仅能够按照我们的需求加入相应的功能,还可以保留原生控件的所有功能 。
public class MyView2 extends Button {
private int cx,cy;
private int radius;
private Paint mPaint;
private int paintColor;
public MyView2(Context context) {
super ( context );
init ();
}
public MyView2(Context context, AttributeSet attrs) {
super ( context, attrs );
init ();
}
public MyView2(Context context, AttributeSet attrs, int defStyleAttr) {
super ( context, attrs, defStyleAttr );
init ();
}
@Override
protected void onDraw(Canvas canvas) {
int width=getWidth ();
int height=getHeight ();
cx=width/2;
cy=height/2;
radius=cx<cy?cy:cx;
canvas.drawCircle ( cx,cy,radius,mPaint );
super.onDraw ( canvas );
}
public void init(){
mPaint=new Paint ();
mPaint.setColor ( Color.RED );
this.setText ( "" );
this.setBackgroundColor ( Color.TRANSPARENT );
}
public void setPaintColor(int color){
paintColor=color;
mPaint.setColor ( paintColor );
invalidate ();
}
//触屏监听器
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction ()){
case MotionEvent.ACTION_DOWN:
setPaintColor ( Color.YELLOW );
return true;
case MotionEvent.ACTION_UP:
setPaintColor ( Color.RED );
return true;
}
return super.onTouchEvent ( event );
}
}
### Listview、GridView、RecyclerView的使用:
一、ListView
二、GridView
三、RecyclerView
### Notification(通知栏信息)
——当系统想要不妨碍操作的情况下通知用户,可以使用Notification展示在屏幕最上方的通知栏内
——如果想要看详细的信息,拉下通知栏可以看到
——系统提供了对于Notification的服务,getSysoutService(NOTIFICATION_SERVICE)为我们返回一个通知服务的接口
——默认的通知栏布局
content title Large icon
Content text Content info
Small icon Time
## Service的概念:
——Service是一种Android的组件 ,可以在后台长时间运行
——Service不提供界面交互
即便用户跳转至另一个应用后,Service仍旧在后台运行
任意应用组件都可以绑定服务,甚至可以用来完成进程间通讯的任务
需要下载时
播放音乐
文件I/O、
一、Service的启动方式:
——Service可以通过两种方式来调用
start
一旦某个组件start一个Service后,Service开始独立运行,不在与原来的组件产生任何关系
bind
某个组件bind一个Service后,Service为组件提供一个接口,近似于客户端,会进行的交互
一、start
public class Service_list extends Service {
private String tag=“Service”;
/*
* 只有在生命周期第一次调用
* /
@Override
public void onCreate() {
Log.d ( tag,“onCreate” );
super.onCreate ();
}
/
* 每次startService启动都会调用
* */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d ( tag,“onStartCommand” );
return super.onStartCommand ( intent, flags, startId );
}
@Override
public void onDestroy() {
Log.d ( tag,“onDestroy” );
super.onDestroy ();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
注意:有些时候我们使用Service的时需要采用隐私启动的方式,但是Android 5.0一出来后,其中有个特性就是Service Intent must be explitict,也就是说从Lollipop开始,service服务必须采用显示方式启动。
有两种解决方法:
1、设置Action和packageName:
Intent mIntent = new Intent();
mIntent.setAction(“XXX.XXX.XXX”);//你定义的service的action
mIntent.setPackage(getPackageName());//这里你需要设置你应用的包名
context.startService(mIntent);
2、将隐式启动转换为显示启动:
public static Intent getExplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List resolveInfo = pm.queryIntentServices(implicitIntent, 0);
// Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
// Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
// Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}
//调用方式如下:
Intent mIntent = new Intent();
mIntent.setAction(“XXX.XXX.XXX”);
Intent eintent = new Intent(getExplicitIntent(mContext,mIntent));
context.startService(eintent);
二、bind
//Service
public class Service_list extends Service {
private String tag=“Service”;
/*
* 只有在生命周期第一次调用
* /
@Override
public void onCreate() {
Log.d ( tag,“onCreate” );
super.onCreate ();
}
/
* 每次startService启动都会调用
* /
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d ( tag,“onStartCommand” );
return super.onStartCommand ( intent, flags, startId );
}
@Override
public void onDestroy() {
Log.d ( tag,“onDestroy” );
super.onDestroy ();
}
/
* 只有在生命周期第一次调用
* */
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d ( tag,“onBind” );
return new Mybind ();
}
public class Mybind extends Binder {
public double avg(double…doubles){
int sum=0;
for (int i=0;i<doubles.length;i++){
sum+=doubles[i];
}
return sum/doubles.length;
}
}
}
//调用
public class Service2 extends AppCompatActivity implements View.OnClickListener {
private String tag = “Service”;
private Button but1;
private Button but2;
private Button but3;
private Button but4;
private Intent intent;
public Service_list.Mybind mybind;
ServiceConnection connection = new ServiceConnection () {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//连接成功,自动调用
mybind = (Service_list.Mybind) service;
Log.d ( tag, “onServiceConnected” );
}
@Override
public void onServiceDisconnected(ComponentName name) {
//连接无效时调用
Log.d ( tag, "onServiceDisconnected" );
}
};
private EditText editText3;
private TextView text5;
private EditText editText2;
private TextView text4;
private EditText editText1;
private TextView text1;
private Button button;
private Button button4;
private TextView textView6;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate ( savedInstanceState );
setContentView ( R.layout.activity_service2 );
initView ();
}
private void initView() {
editText3 = (EditText) findViewById ( R.id.editText3 );
text5 = (TextView) findViewById ( R.id.text5 );
editText2 = (EditText) findViewById ( R.id.editText2 );
text4 = (TextView) findViewById ( R.id.text4 );
editText1 = (EditText) findViewById ( R.id.editText1 );
text1 = (TextView) findViewById ( R.id.text1 );
button = (Button) findViewById ( R.id.button );
button.setOnClickListener ( this );
button4 = (Button) findViewById ( R.id.button4 );
button4.setOnClickListener ( this );
textView6 = (TextView) findViewById ( R.id.textView6 );
textView6.setOnClickListener ( this );
}
@Override
public void onClick(View v) {
switch (v.getId ()) {
case R.id.button:
intent = new Intent ();
intent.setAction ( "com.example.myapplication.Service" );
intent.setPackage ( getPackageName () );
bindService ( intent, connection, BIND_AUTO_CREATE );
break;
case R.id.button4:
double yu=Double.valueOf (editText1.getText ().toString () );
double num=Double.valueOf (editText2.getText ().toString () );
double yin=Double.valueOf (editText3.getText ().toString () );
double a=mybind.avg ( yu,num,yin );
textView6.setText ( "平均分数:"+a );
break;
}
}
}
三、系统服务:
1、由于是Android原生代码,可以通过Android代码来对服务进行交互
2、Android将Binder封装成普通的Manager类,代码调用时无法察觉是使用了Service
3、这些服务通过Context.getSystemService(String name)来获得
name决定了获得不同的Manager类,不同的Manager类有各自的方法来调用系统功能或是访问系统状态
一、常用的系统服务:
1、POWER_SERVICE("power") PowerManager电源管理
2、NOTIFICATION_SERVICE("notification") NotificationManager通知的管理
3、LOCATION_SERVICE("location") LocationManager定位的控制
4、CONNECTIVITY_SERVICE("connection") ConnectivityManager网络连接的管理
## ShraredPreference存储:
一、数据存储的意义:
——保存用户私有数据和配置
——比如音效设置,音乐文件,视频文件,短信,联系人
——需要在关机后重启仍能有效
——需要存储到外部介质中
二、使用SharedPrefreences
——一种轻量级的数据存取方法,以键值对来存储应用程序的配置信息
——只能存储基本的数据类型:boolean,float,int,long,string
——以XML文件的格式保存,位于/data/data/Package_name/shared_prefs目录下
## 文件存储:
——使用文件系统
——使用SDCard
一、使用文件系统:
——android使用的是基于Linux的文件系统,开发人员可以建立和访问程序自身的私有文件,也可以访问保存在资源目录中得原始文件和XML文件,还可以在SD卡等外部存储设备中保存文件。
——Android允许应用程序创建仅能够自身访问的私有文件,文件保存在设备的内部存储器上,在Linux系统上 的/data/data/<package_name>中。
常用FileInputStream,FileOutputStream类结合openFileOutput,openFileInput方法完成对文件的读写。