柚子快报邀请码778899分享:安卓零碎知识集中
因为安卓的知识点较多。平时动看看西看看,easy把东西搞混和搞忘,因此放在这里集中起来,长期更新。
一、AlarmManager的使用
1、AlarmManager。顾名思义,就是“提醒”,是Android中经常使用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的Intent。简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent,通常我们使用 PendingIntent,PendingIntent能够理解为Intent的封装包,简单的说就是在Intent上在加个指定的动作。在使用Intent的时候,我们还须要在运行startActivity、startService或sendBroadcast才干使Intent实用。而PendingIntent的话就是将这个动作包括在内了。
定义一个PendingIntent对象。
PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);
2、AlarmManager的经常用法有三个:
(1)set(int type,long startTime。PendingIntent pi);
该方法用于设置一次性闹钟,第一个參数表示闹钟类型,第二个參数表示闹钟运行时间,第三个參数表示闹钟响应动作。
(2)setRepeating(int type,long startTime。long intervalTime,PendingIntent pi)。
该方法用于设置反复闹钟。第一个參数表示闹钟类型。第二个參数表示闹钟首次运行时间,第三个參数表示闹钟两次运行的间隔时间。第三个參数表示闹钟响应动作。
(3)setInexactRepeating(int type,long startTime,long intervalTime。PendingIntent pi);
该方法也用于设置反复闹钟,与第二个方法相似,只是其两个闹钟运行的间隔时间不是固定的而已。
3、三个方法各个參数详悉:
(1)int type: 闹钟的类型。经常使用的有5个值:AlarmManager.ELAPSED_REALTIME、 AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、 AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP。
AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动開始),状态值为3。
AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡眠状态下会唤醒系统并运行提示功能,该状态下闹钟也使用相对时间,状态值为2;
AlarmManager.RTC表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间。即当前系统时间,状态值为1;
AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并运行提示功能,该状态下闹钟使用绝对时间。状态值为0;
AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之中的一个,该状态下闹钟也是用绝对时间,状态值为4。只是本状态好像受SDK版本号影响,某些版本号并不支持;
(2)long startTime: 闹钟的第一次运行时间。以毫秒为单位。能够自己定义时间,只是一般使用当前时间。须要注意的是,本属性与第一个属性(type)密切相关,假设第一个參数对 应的闹钟使用的是相对时间(ELAPSED_REALTIME和ELAPSED_REALTIME_WAKEUP),那么本属性就得使用相对时间(相对于 系统启动时间来说)。比方当前时间就表示为:SystemClock.elapsedRealtime()。假设第一个參数相应的闹钟使用的是绝对时间
(RTC、RTC_WAKEUP、POWER_OFF_WAKEUP),那么本属性就得使用绝对时间。比方当前时间就表示 为:System.currentTimeMillis()。
(3)long intervalTime:对于后两个方法来说。存在本属性,表示两次闹钟运行的间隔时间。也是以毫秒为单位。
(4)PendingIntent pi: 绑定了闹钟的运行动作,比方发送一个广播、给出提示等等。PendingIntent是Intent的封装类。须要注意的是,假设是通过启动服务来实现闹钟提 示的话,PendingIntent对象的获取就应该採用Pending.getService(Context c,int i,Intent intent,int j)方法。假设是通过广播来实现闹钟提示的话,PendingIntent对象的获取就应该採用
PendingIntent.getBroadcast(Context c,int i,Intent intent,int j)方法;假设是採用Activity的方式来实现闹钟提示的话。PendingIntent对象的获取就应该採用 PendingIntent.getActivity(Context c,int i,Intent intent,int j)方法。假设这三种方法错用了的话。尽管不会报错,可是看不到闹钟提示效果。
4.举例说明:定义一个闹钟,5秒钟反复响应。
(1)MainActivity,在onCreate中完毕:
[java] view plaincopy?
//创建Intent对象,action为ELITOR_CLOCK,附加信息为字符串“你该打酱油了” Intent intent = new Intent("ELITOR_CLOCK"); intent.putExtra("msg","你该打酱油了"); //定义一个PendingIntent对象,PendingIntent.getBroadcast包括了sendBroadcast的动作。 //也就是发送了action 为"ELITOR_CLOCK"的intent PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0); //AlarmManager对象,注意这里并非new一个对象,Alarmmanager为系统级服务 AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); //设置闹钟从当前时间開始,每隔5s运行一次PendingIntent对象pi。注意第一个參数与第二个參数的关系 // 5秒后通过PendingIntent pi对象发送广播 am.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),5*1000,pi);
那么启动MainActivity之后,因为定义了AlarmManager am,而且调用了am.setRepeating(...)函数,则系统每隔5s将会通过pi启动intent发送广播。其action为ELITOR_CLOCK。所以我们须要在Manifest.xml中注冊一个receiver,同一时候自定义一个广播接收器类。
(2)定义一个广播接收器类MyReceiver,重写onReceive()函数。
[java] view plaincopy?
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Log.d("MyTag", "onclock......................"); String msg = intent.getStringExtra("msg"); Toast.makeText(context,msg,Toast.LENGTH_SHORT).show(); } }
(3)在Manifest.xml中注冊广播接收器:
[html] view plaincopy?
二、Fragment的使用方法
在Activity用Fragment替换之前已有的布局须要填充满的话。改动Fragment里面返回的布局。
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.i(Tag, "onCreateView");
View view = LayoutInflater.from(getActivity()).inflate(R.layout.f1,
null);
// layout = new FrameLayout(getActivity());
view.setLayoutParams(new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
return view;
}
(1)首先了解其生命周期
onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想相应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相相应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其它的全部方法假设你重写了,必须调用父类对于该方法的实现。
(2)静态使用
定义好Fragment类,加入至xml布局中。
(3)动态使用
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
mWeixin = new ContentFragment();
transaction.replace(R.id.id_content, mWeixin);
transaction.addToBackStack(null);
transaction.commit();
(4)通信
由于全部的Fragment都是依附于Activity的,所以通信起来并不复杂,大概归纳为:
a、假设你Activity中包括自己管理的Fragment的引用,能够通过引用直接訪问全部的Fragment的public方法
b、假设Activity中未保存不论什么Fragment的引用,那么没关系,每一个Fragment都有一个唯一的TAG或者ID,能够通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得不论什么Fragment实例。然后进行操作。
c、在Fragment中能够通过getActivity得到当前绑定的Activity的实例,然后进行操作。
注:假设在Fragment中须要Context,能够通过调用getActivity(),假设该Context须要在Activity被销毁后还存在,则使用getActivity().getApplicationContext()。
(5)处理配置变化
当你执行之后。不断的旋转屏幕,你会发现每旋转一次屏幕。屏幕上就多了一个FragmentOne的实例,而且后台log会打印出很多套生命周期的回调。
07-20 08:18:46.651: E/FragmentOne(1633): onCreate
07-20 08:18:46.651: E/FragmentOne(1633): onCreate
07-20 08:18:46.651: E/FragmentOne(1633): onCreate
07-20 08:18:46.681: E/FragmentOne(1633): onCreateView
07-20 08:18:46.831: E/FragmentOne(1633): onCreateView
07-20 08:18:46.891: E/FragmentOne(1633): onCreateView
这是为什么呢,由于当屏幕发生旋转。Activity发生又一次启动,默认的Activity中的Fragment也会跟着Activity又一次创建;这样造成当旋转的时候,本身存在的Fragment会又一次启动。然后当运行Activity的onCreate时,又会再次实例化一个新的Fragment,这就是出现的原因。
那么怎样解决呢:
事实上通过检查onCreate的參数Bundle savedInstanceState就能够推断,当前是否发生Activity的又一次创建:
默认的savedInstanceState会存储一些数据,包含Fragment的实例:通过打印能够看出:
07-20 08:23:12.952: E/FragmentOne(1782): Bundle[{android:fragments=android.app.FragmentManagerState@40d0b7b8, android:viewHierarchyState=Bundle[{android:focusedViewId=2131230721, android:views=android.util.SparseArray@40d0af68}]}]
所以。我们简单改一下代码,仅仅有在savedInstanceState==null时,才进行创建Fragment实例:
package com.zhy.zhy_fragments;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
public class MainActivity extends Activity
{
private static final String TAG = "FragmentOne";
private FragmentOne mFOne;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Log.e(TAG, savedInstanceState+"");
if(savedInstanceState == null)
{
mFOne = new FragmentOne();
FragmentManager fm = getFragmentManager();
FragmentTransaction tx = fm.beginTransaction();
tx.add(R.id.id_content, mFOne, "ONE");
tx.commit();
}
}
}
如今不管进行多次旋转都仅仅会有一个Fragment实例在Activity中。
如今还存在一个问题。就是又一次绘制时,Fragment发生重建。原本的数据怎样保持?
事实上和Activity类似,Fragment也有onSaveInstanceState的方法。在此方法中进行保存数据,然后在onCreate或者onCreateView或者onActivityCreated进行恢复都能够。
因为篇幅原因,就不贴測试代码了。
三、Popwindow的使用
popwindow可实现导航栏上的弹出菜单。主要注意下面几点:
(1)找准定位。
通过产生事件的View,获取其Y坐标,加上其本身的高度就是弹出框的Y坐标;获取View的X。即是弹出框的X。
获取位置:
int is[] = new int[2]; v.getLocationOnScreen(is);
在该位置显示:
popupWindow.showAtLocation(v, Gravity.NO_GRAVITY, screenWidth - 10- (popupWindow.getWidth() / 2), h + v.getHeight());
(3)若没有弹出
加入以下语句
ColorDrawable cd = new ColorDrawable(-0000);
popupWindow.setBackgroundDrawable(cd);// 加上这句试一试
四、用Action指定活动并用列表显示出来
(1)查询相关的activity
String markString = "com.aretha.demobundle.DEMO";
PackageManager packageManager;
List
list; packageManager = getPackageManager(); list = packageManager.queryIntentActivities(new Intent(markString),
PackageManager.GET_META_DATA);(2)用适配器显示信息
((TextView) view.findViewById(android.R.id.text1)).setText(info
.loadLabel(packageManager));(3)监听列表,跳转到相关的Activity中去
ResolveInfo info = list.get(arg2);
ActivityInfo activityInfo = info.activityInfo;
Intent intent = new Intent();
intent.setComponent(new ComponentName(activityInfo.packageName,
activityInfo.name));
startActivity(intent);
柚子快报邀请码778899分享:安卓零碎知识集中
发表评论