常用组件
Toast
这是个常用的进行消息提示组件。
void midToast(String str, int showTime)
{
Toast toast = Toast.makeText(global_context, str, showTime);
toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL , 0, 0); //设置显示位置
TextView v = (TextView) toast.getView().findViewById(android.R.id.message);
v.setTextColor(Color.YELLOW); //设置字体颜色
toast.show();
}
AlertDialog(对话框)基本运用
public class MainActivity extends AppCompatActivity {
private Button btn_one;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_one = findViewById(R.id.btn_one);
btn_one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("提示").setMessage("这是一个普通的对话框").setIcon(R.mipmap.icon_man).setCancelable(true);
//设置正面按钮
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
Toast.makeText(MainActivity.this, "你点击了确定", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
//设置反面按钮
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "你点击了取消", Toast.LENGTH_SHORT).show();
dialogInterface.dismiss();
}
});
//设置中立按钮
builder.setNeutralButton("保密", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "你点击了保密", Toast.LENGTH_SHORT).show();
dialogInterface.dismiss();
}
});
AlertDialog dialog = builder.create(); //创建AlterDialog对象
//对话框显示的监听事件
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
Log.e("TAG", "对话框显示了");
}
});
//对话框消失的监听事件
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
Log.e("TAG", "对话框消失了");
}
});
dialog.show(); //显示对话框
}
});
}
Intent与IntentFilter
-
Action
<action android:name="android.intent.action.MAIN" /> intent.setAction(Intent.MAIN)
-
Category
Category用于提供额外的附加类别信息,两者通常结合使用,一个Intent对象只能有一个Action,可以有多个
<category android:name="android.intent.category.LAUNCHER" /> intent.addCategorie(Intent.CATEGORY_LAUNCHER)
-
Data(数据), Type(MIME类型)
Data同创用于向Action属性提供操作的数据,接收一个URI对象,URI的格式 scheme://host:port/path
Type通常用于指定Data所制定的Uri对应的MIME类型,比如能够显示图片数据的组建不应该用来播放音频文件
可以是自定义的MIME类型,只要符合abc/xyz格式的字符串就可以
<data android:mimeType="Inetnt的type属性" android:scheme="Data的scheme协议头" android:host="Data的主机号" android:port="Data的端口号" android:path="Data的路径" android:pathPrefix="Data的path前缀" android:pathPattern="Data属性的path的字符串模板" / >
-
Extras(额外)
通常用于多个Action之间的数据交换,Extras属性是一个Bundle对象,通过键值对进行数据的存储
单个变量:intent.putintExtra(),getputExtra() Bundle:intent.putExtras(),getExtras()
-
Flags(标记)
表示不同来源的标记,多数用于只是Android如何启动Activity以及启动后如何对待,标记都是定义在Intent类中,比如:FLAG_ACTIVITY)SINGLE_TOP:
相当于加载模式总 singleTop模式,所有标记都是整数类型
Intent intent = new Intent(); //点击返回主界面 // intent.setAction(Intent.ACTION_MAIN); // intent.addCategory(Intent.CATEGORY_HOME); //点击打开百度 intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com")); startActivity(intent);
-
隐式Intent
常用Intent合集
//===============================================================
//1.拨打电话
// 给移动客服10086拨打电话
Uri uri = Uri.parse("tel:10086");
Intent intent = new Intent(Intent.ACTION_DIAL, uri);
startActivity(intent);
//===============================================================
//2.发送短信
// 给10086发送内容为“Hello”的短信
Uri uri = Uri.parse("smsto:10086");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
intent.putExtra("sms_body", "Hello");
startActivity(intent);
//3.发送彩信(相当于发送带附件的短信)
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra("sms_body", "Hello");
Uri uri = Uri.parse("content://media/external/images/media/23");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("image/png");
startActivity(intent);
//===============================================================
//4.打开浏览器:
// 打开百度主页
Uri uri = Uri.parse("http://www.baidu.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
//===============================================================
//5.发送电子邮件:(阉割了Google服务的没戏!!!!)
// 给someone@domain.com发邮件
Uri uri = Uri.parse("mailto:someone@domain.com");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(intent);
// 给someone@domain.com发邮件发送内容为“Hello”的邮件
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, "someone@domain.com");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Hello");
intent.setType("text/plain");
startActivity(intent);
// 给多人发邮件
Intent intent=new Intent(Intent.ACTION_SEND);
String[] tos = {"1@abc.com", "2@abc.com"}; // 收件人
String[] ccs = {"3@abc.com", "4@abc.com"}; // 抄送
String[] bccs = {"5@abc.com", "6@abc.com"}; // 密送
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_BCC, bccs);
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Hello");
intent.setType("message/rfc822");
startActivity(intent);
//===============================================================
//6.显示地图:
// 打开Google地图中国北京位置(北纬39.9,东经116.3)
Uri uri = Uri.parse("geo:39.9,116.3");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
//===============================================================
//7.路径规划
// 路径规划:从北京某地(北纬39.9,东经116.3)到上海某地(北纬31.2,东经121.4)
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=39.9 116.3&daddr=31.2 121.4");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
//===============================================================
//8.多媒体播放:
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/foo.mp3");
intent.setDataAndType(uri, "audio/mp3");
startActivity(intent);
//获取SD卡下所有音频文件,然后播放第一首=-=
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
//===============================================================
//9.打开摄像头拍照:
// 打开拍照程序
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);
// 取出照片数据
Bundle extras = intent.getExtras();
Bitmap bitmap = (Bitmap) extras.get("data");
//另一种:
//调用系统相机应用程序,并存储拍下来的照片
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
time = Calendar.getInstance().getTimeInMillis();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment
.getExternalStorageDirectory().getAbsolutePath()+"/tucue", time + ".jpg")));
startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE);
//===============================================================
//10.获取并剪切图片
// 获取并剪切图片
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.putExtra("crop", "true"); // 开启剪切
intent.putExtra("aspectX", 1); // 剪切的宽高比为1:2
intent.putExtra("aspectY", 2);
intent.putExtra("outputX", 20); // 保存图片的宽和高
intent.putExtra("outputY", 40);
intent.putExtra("output", Uri.fromFile(new File("/mnt/sdcard/temp"))); // 保存路径
intent.putExtra("outputFormat", "JPEG");// 返回格式
startActivityForResult(intent, 0);
// 剪切特定图片
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setClassName("com.android.camera", "com.android.camera.CropImage");
intent.setData(Uri.fromFile(new File("/mnt/sdcard/temp")));
intent.putExtra("outputX", 1); // 剪切的宽高比为1:2
intent.putExtra("outputY", 2);
intent.putExtra("aspectX", 20); // 保存图片的宽和高
intent.putExtra("aspectY", 40);
intent.putExtra("scale", true);
intent.putExtra("noFaceDetection", true);
intent.putExtra("output", Uri.parse("file:///mnt/sdcard/temp"));
startActivityForResult(intent, 0);
//===============================================================
//11.打开Google Market
// 打开Google Market直接进入该程序的详细页面
Uri uri = Uri.parse("market://details?id=" + "com.demo.app");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
//===============================================================
//12.进入手机设置界面:
// 进入无线网络设置界面(其它可以举一反三)
Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);
startActivityForResult(intent, 0);
//===============================================================
//13.安装apk:
Uri installUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);
//===============================================================
//14.卸载apk:
Uri uri = Uri.fromParts("package", strPackageName, null);
Intent it = new Intent(Intent.ACTION_DELETE, uri);
startActivity(it);
//===============================================================
//15.发送附件:
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/eoe.mp3");
sendIntent.setType("audio/mp3");
startActivity(Intent.createChooser(it, "Choose Email Client"));
//===============================================================
//16.进入联系人页面:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(People.CONTENT_URI);
startActivity(intent);
//===============================================================
//17.查看指定联系人:
Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);//info.id联系人ID
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(personUri);
startActivity(intent);
//===============================================================
//18.调用系统编辑添加联系人(高版本SDK有效):
Intent it = newIntent(Intent.ACTION_INSERT_OR_EDIT);
it.setType("vnd.android.cursor.item/contact");
//it.setType(Contacts.CONTENT_ITEM_TYPE);
it.putExtra("name","myName");
it.putExtra(android.provider.Contacts.Intents.Insert.COMPANY, "organization");
it.putExtra(android.provider.Contacts.Intents.Insert.EMAIL,"email");
it.putExtra(android.provider.Contacts.Intents.Insert.PHONE,"homePhone");
it.putExtra(android.provider.Contacts.Intents.Insert.SECONDARY_PHONE,"mobilePhone");
it.putExtra( android.provider.Contacts.Intents.Insert.TERTIARY_PHONE,"workPhone");
it.putExtra(android.provider.Contacts.Intents.Insert.JOB_TITLE,"title");
startActivity(it);
//===============================================================
//19.调用系统编辑添加联系人(全有效):
Intent intent = newIntent(Intent.ACTION_INSERT_OR_EDIT);
intent.setType(People.CONTENT_ITEM_TYPE);
intent.putExtra(Contacts.Intents.Insert.NAME, "My Name");
intent.putExtra(Contacts.Intents.Insert.PHONE, "+1234567890");
intent.putExtra(Contacts.Intents.Insert.PHONE_TYPE,Contacts.PhonesColumns.TYPE_MOBILE);
intent.putExtra(Contacts.Intents.Insert.EMAIL, "com@com.com");
intent.putExtra(Contacts.Intents.Insert.EMAIL_TYPE, Contacts.ContactMethodsColumns.TYPE_WORK);
startActivity(intent);
//===============================================================
//20.打开另一程序
Intent i = new Intent();
ComponentName cn = new ComponentName("com.example.jay.test",
"com.example.jay.test.MainActivity");
i.setComponent(cn);
i.setAction("android.intent.action.MAIN");
startActivityForResult(i, RESULT_OK);
//===============================================================
//21.打开录音机
Intent mi = new Intent(Media.RECORD_SOUND_ACTION);
startActivity(mi);
//===============================================================
//22.从google搜索内容
Intent intent = new Intent();
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,"searchString")
startActivity(intent);
//===============================================================
四大组件之Activity
-
启动一个Activity的几种方式
-
显示启动: 通过包名来启动,写法如下
//1.最常见的 startActivity(new Intent(当前Act.this,要启动的Act.class)); //通过Intent的ComponentName: ComponentName cn = new ComponentName("当前Act的全限定类名","启动Act的全限定类名") ; Intent intent = new Intent() ; intent.setComponent(cn) ; startActivity(intent) ; //初始化Intent时指定包名: Intent intent = new Intent("android.intent.action.MAIN"); intent.setClassName("当前Act的全限定类名","启动Act的全限定类名"); startActivity(intent);
-
隐式启动: 通过Intent-filter的Action,Category或data来实现 这个是通过Intent的intent-filter来实现的
<activity android:name=".MainActivity3" android:label="第三个Activity"> <intent-filter> <action android:name="third_action"/> <category android:name="third_category"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
//启动第三个activity Intent it = new Intent(); it.setAction("third_action"); it.addCategory("third_category"); startActivity(it);
-
直接通过包名启动apk:
Intent intent = getPackageManager().getLaunchIntentForPackage ("apk第一个启动的Activity的全限定类名") ; if(intent != null) startActivity(intent) ;
-
-
横竖屏切换与状态保存
<activity android:name=".MainActivity3" android:label="第三个Activity" android:screenOrientation="横竖屏"> <intent-filter> <action android:name="third_action" /> <category android:name="third_category" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
- unspecified:默认值 由系统来判断显示方向.判定的策略是和设备相关的,所以不同的设备会有不同的显示方向。
- landscape:横屏显示(宽比高要长)
- portrait:竖屏显示(高比宽要长)
- user:用户当前首选的方向
- behind:和该Activity下面的那个Activity的方向一致(在Activity堆栈中的)
- sensor:有物理的感应器来决定。如果用户旋转设备这屏幕会横竖屏切换。
- nosensor:忽略物理感应器,这样就不会随着用户旋转设备而更改了("unspecified"设置除外)。
-
Activity间的数据传递
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vn79vvF2-1616552745252)(imgs/activity_data_pass.jpg)]
四大组件之Service
StartService启动Service的调用顺序
TestService1.java
public class TestService1 extends Service {
private final String TAG = "TestService1";
public TestService1() {
}
//必须要实现的方法
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
Log.i(TAG, "onBind方法被调用");
return null;
}
//Service被创建时调用
@Override
public void onCreate() {
Log.i(TAG, "onCreate方法被调用!");
super.onCreate();
}
//Service被启动时调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand方法被调用!");
return super.onStartCommand(intent, flags, startId);
}
//Service被关闭之前回调
@Override
public void onDestroy() {
Log.i(TAG, "onDestory方法被调用!");
super.onDestroy();
}
}
AndroidManifest.xml完成Service注册
<service
android:name=".TestService1"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.myapplication.TEST_SERVICE1"/>
</intent-filter>
</service>
MainActivity 启动 Service的编写
//创建启动Service的Intent,以及Intent属性
final Intent intent = new Intent();
intent.setAction("com.example.myapplication.TEST_SERVICE1");
intent.setPackage("com.example.myapplication");
//为两个按钮设置点击事件,分别是启动与停止service
btn_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(intent);
}
});
btn_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stopService(intent);
}
});
结果分析
onBind()方法并没有被调用,多次点击Service,只会重复的调用onStartCommand方法!无论我们启动多少次Service,一个StopService就会停止Service!
验证BindService启动Service的调用顺序
- ServiceConnection对象:监听访问者与Service间的连接情况,如果成功连接,回调 onServiceConnected(),如果异常终止或者其他原因终止导致Service与访问者断开 连接则回调onServiceDisconnected方法,调用unBindService()不会调用该方法!
- onServiceConnected**方法中有一个IBinder对象,该对象即可实现与被绑定Service 之间的通信!**我们再开发Service类时,默认需要实现IBinder onBind()方法,该方法返回的 IBinder对象会传到ServiceConnection对象中的onServiceConnected的参数,我们就可以 在这里通过这个IBinder与Service进行通信!
Service问题:
java.lang.NullPointerException: Attempt to invoke virtual method 'int com.example.myapplication.TestService2$MyBinder.getCount()' on a null object reference
在service中定义的count变量,无法获取,定义的线程不执行
public class TestService2 extends Service {
private final String TAG = "TestService2";
private int count=1;
private boolean quit;
public TestService2() {
}
//定义onbinder方法所返回的对象
private MyBinder binder = new MyBinder();
public class MyBinder extends Binder {
public int getCount() {
return count;
}
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind方法被调用!");
Log.i(TAG, "count值为!"+count);
return binder;
}
//Service被创建时回调
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate方法被调用!");
//创建一个线程动态的修改count的值
new Thread() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
}.start();
}
//Service断开连接时回调
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind方法被调用!");
return true;
}
//Service被关闭前回调
@Override
public void onDestroy() {
super.onDestroy();
this.quit = true;
Log.i(TAG, "onDestroyed方法被调用!");
}
@Override
public void onRebind(Intent intent) {
Log.i(TAG, "onRebind方法被调用!");
super.onRebind(intent);
}
- bindService中Intent所担任的角色?绑定service
- Service中ServiceConnected对象来监听访问者与service间的连接情况,如果成功连接或者失败连接都会调用相应的方法.
- ServiceConnected中Ibinder对象实现与被绑定的Service之间的通信,开发service类时,默认需要实现IBinder onBind()方法,该方法返回的IBinder对象会传到ServiceCOnnection对象中的onServiceConnected的参数,我们就可以在这里通过这个IBinder与Service进行通信
MainActivity.java
public class MainActivity extends AppCompatActivity {
//bindService
private Button btn_bind;
private Button btn_cancel;
private Button btn_status;
//保持所启动的Service的IBinder对象,同时定义一个ServiceConnection对象
TestService2.MyBinder binder;
private ServiceConnection conn = new ServiceConnection() {
//Activity与Service连接成功时回调该方法
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
//通过这个IBinder与Service进行通信
System.out.println("----------------Service Connected---------------");
binder = (TestService2.MyBinder) service;
}
//Activity与Service断开连接时回调该方法
@Override
public void onServiceDisconnected(ComponentName componentName) {
System.out.println("------Service DisConnected-------");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//bindService
btn_bind = findViewById(R.id.btn_bind);
btn_cancel = findViewById(R.id.btn_cancel);
btn_status = findViewById(R.id.btn_status);
final Intent it1 = new Intent();
it1.setAction("com.example.myapplication.TEST_SERVICE2");
it1.setPackage("com.example.myapplication");
btn_bind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//锁定Service
bindService(it1, conn, Service.BIND_AUTO_CREATE);
}
});
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//解除锁定
unbindService(conn);
}
});
//获取Service状态
btn_status.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), "Service的count的值为:"
+ binder.getCount(), Toast.LENGTH_SHORT).show();
}
});
}
}
IntentService的使用
public class TestService3 extends IntentService {
private final String TAG = "hehe";
public TestService3() {
super("TestService3");
}
//必须重写的核心方法
@Override
protected void onHandleIntent(Intent intent) {
//Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
String action = intent.getExtras().getString("param");
if (action.equals("s1")) Log.i(TAG, "启动service1");
else if (action.equals("s2")) Log.i(TAG, "启动service2");
else if (action.equals("s3")) Log.i(TAG, "启动service3");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//重写其他方法,用于查看方法的调用顺序
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG,"onBind");
return super.onBind(intent);
}
@Override
public void onCreate() {
Log.i(TAG,"onCreate");
super.onCreate();
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.i(TAG,"onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
Log.i(TAG,"setIntentRedelivery");
}
@Override
public void onDestroy() {
Log.i(TAG,"onDestroy");
super.onDestroy();
}
}
Acitvity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent it1 = new Intent("com.example.myapplication.intentservice");
it1.setPackage("com.example.myapplication");
Bundle b1 = new Bundle();
b1.putString("param", "s1");
it1.putExtras(b1);
Intent it2 = new Intent("com.example.myapplication.intentservice");
it2.setPackage("com.example.myapplication");
Bundle b2 = new Bundle();
b2.putString("param", "s2");
it2.putExtras(b2);
Intent it3 = new Intent("com.example.myapplication.intentservice");
it3.setPackage("com.example.myapplication");
Bundle b3 = new Bundle();
b3.putString("param", "s3");
it3.putExtras(b3);
//接着启动多次IntentService,每次启动都会创建一个工作线程
//但始终只要一个IntentService实例
startService(it1);
startService(it2);
startService(it3);
}
四大组件之BroadcastReceiver
1>注册广播的方式
动态注册
就是Java代码中指定IntentFilter,然后添加不同的Action即可,想监听什么广播就写什么Action,另外动态注册的广播,一定要调用unregisterReceiver让广播取消注册
静态注册
动态注册需要程序启动后才能接受广播,静态广播就弥补了这个短板,在AndroidManifest中订制就可以让程序在未启动的情况下接收广播了
2>动态注册实例(监听网络状态变化)
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"网络状态发生改变~", Toast.LENGTH_SHORT).show();
}
}
Mainfest
<receiver
android:name=".broadres.MyReceiver"
android:enabled="true"
android:exported="true">
</receiver>
Activity
public class MainActivity extends AppCompatActivity {
MyReceiver myReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//核心代码
myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(myReceiver, intentFilter);
}
//取消广播
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myReceiver);
}
}
3>静态注册实例(接收开机广播)
4>发送广播(●’◡’●)
布局神器 Fragment
fragment静态加载
fragment动态加载
ListView优化
ViewHolder
启动该一个Activity的几种方式
显示启动:通过包名来启动,写法如下
-
最常见的:
startActivity(new Intennt(当前Act.this,要启动的Act.class));
-
通过Intent的ComponetName:
ComponentName cn=new ComponentName("当前Act的全限定类名","启动Act的全限定类名"); Intent intent =new Intent(); intent.setComponent(cn); startActivity(intent);
-
初始化Intent时指定包名:
Intent intent = new Intent("android.intent.action.MAIN"); intent.setClassName("当前Act的全限定类名","启动Act的全限定类名"); startActivity(intent);
activity给Fragment传递数据通信
一 通过自定义接口来实现
该方法没有使用Bundle 来传递数据,而是通过接口来进行监听作用
定义一个接口,作为监听器来使用=====>>测试接口作为某个实体类的监听器
public interface ToFragmentListener {
void onTypeClick(String message);
}
该接口中只要一个方法就是接受信息并作出操作
Fragment实现该方法
public class BasicFragment extends Fragment implements ToFragmentListener{
...
private View initView() {
FrameLayout rootView = (FrameLayout) LayoutInflater.from(this.getContext()).inflate(R.layout.fragment_basic, null);
//获取Fragment中的组件
textView_basic_main = rootView.findViewById(R.id.textView_basic_main);
return rootView;
}
@Override
public void onTypeClick(String message) {
//为组件赋值
textView_basic_main.setText(message);
}
}
在Activtiy中,创建该Fragment实例对象,并赋值给接口==>>>多态??
通过接口来调用方法,在方法中传递需要传递的参数android:background="#E0E0E0"
public class MainActivity extends FragmentActivity {
/*
fragment
*/
private ToFragmentListener mFragmentListener;
private BasicFragment basicFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
//为fragment对象赋值
basicFragment = new BasicFragment();
//这步是关键,因为Fragment实现了该接口,所以可以直接把Fragment实例赋值给接口引用
mFragmentListener = basicFragment;
}
/**
* 测试按钮
* @param view
*/
public void fun_test(View view) {
if(null != mFragmentListener){
mFragmentListener.onTypeClick("来自Activity的实时数据");
}
}
}
二 通过bundle来传递数据
步骤1: 创建布局文件
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="我是Activity" />
<FrameLayout
android:layout_below="@+id/fragment_container"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="500dp"/>
</LinearLayout>
步骤2: 定义activity
public class MainActivity extends AppCompatActivity {
TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = findViewById(R.id.text);
//步骤1: 创建fragment
myfragment myfragment = new myfragment();
Bundle bundle = new Bundle();
bundle.putString("message", "wocaonima");
myfragment.setArguments(bundle);
//步骤2: 获取Fragment对象
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, myfragment).commit();
}
}
步骤3: 定义fragment布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/purple_200"
>
<TextView
android:id="@+id/fragment"
android:text="我是fragment"
android:layout_gravity="center"
android:textSize="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/text"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="等待Activity发送消息" />
<Button
android:id="@+id/button"
android:layout_gravity="center"
android:text="点击接收Activity消息"
android:layout_centerInParent="true"
android:textSize="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
步骤4: 创建fragment
public class myfragment extends Fragment {
Button button;
TextView text;
Bundle bundle;
String message;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.fragment, container, false);
//设置布局文件
button = contentView.findViewById(R.id.button);
text= contentView.findViewById(R.id.text);
//步骤1 通过getArgments()获取从Activity传过来的全部值
bundle = this.getArguments();
//步骤2 获取某一值
message = bundle.getString("message");
//步骤3 设置按钮,将设置的值显示出来
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
text.setText(message);
}
});
return contentView;
}
}
fragment给activity传递数据
采用接口回调方式
接口回调:
把实现了某一个接口的类所创建的引用赋给该接口声明的变量,通过该接口变量 调用该实现类对象的实 现的接口方法
// 接口声明的变量
Com com;
// 实现了Com接口的类(Com1)所创建的对象的引用 赋给 该接口声明的变量
Com com = new Com1;
// 通过该接口变量(com) 调用 该实现类对象(Com1)的实现的接口方法(carson())
com.carson()
- 步骤1:在
Activity
的布局文件定义1占位符(FrameLayout
)
activity_main.xml
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="scut.carson_ho.fragment_2_activity.MainActivity">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="等待Fragment发送消息" />
<Button
android:id="@+id/button"
android:layout_below="@+id/text"
android:text="点击接收Fragment消息"
android:layout_centerInParent="true"
android:textSize="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<FrameLayout
android:layout_below="@+id/button"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="500dp"/>
</RelativeLayout>
- 步骤2:设置
Fragment
的布局文件
fragment.xml
<?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"
>
<TextView
android:id="@+id/fragment"
android:text="我是fragment"
android:gravity="center"
android:textSize="30dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"/>
</LinearLayout>
- 步骤3:设置回调接口
该接口用于用于Activity
与Fragment
通信
ICallBack.java
public interface ICallBack {
void get_message_from_Fragment(String string);
}
- 步骤4:设置
Fragment
的类文件
mFragment.java
public class mFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.fragment, container, false);
// 设置布局文件
return contentView;
}
// 设置 接口回调 方法
public void sendMessage(ICallBack callBack){
callBack.get_message_from_Fragment("消息:我来自Fragment");
}
}