• 安卓零碎知识集中


           因为安卓的知识点较多。平时动看看西看看,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中完毕:

    1. //创建Intent对象,action为ELITOR_CLOCK,附加信息为字符串“你该打酱油了”   
    2. Intent intent = new Intent("ELITOR_CLOCK");  
    3. intent.putExtra("msg","你该打酱油了");    
    4.   
    5. //定义一个PendingIntent对象,PendingIntent.getBroadcast包括了sendBroadcast的动作。   
    6. //也就是发送了action 为"ELITOR_CLOCK"的intent   
    7. PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);    
    8.   
    9. //AlarmManager对象,注意这里并非new一个对象,Alarmmanager为系统级服务   
    10. AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);    
    11.   
    12. //设置闹钟从当前时间開始,每隔5s运行一次PendingIntent对象pi。注意第一个參数与第二个參数的关系   
    13. // 5秒后通过PendingIntent pi对象发送广播   
    14. 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()函数。

    1. public class MyReceiver extends BroadcastReceiver  
    2. {  
    3.   
    4.     @Override  
    5.     public void onReceive(Context context, Intent intent)  
    6.     {  
    7.         // TODO Auto-generated method stub   
    8.         Log.d("MyTag""onclock......................");  
    9.         String msg = intent.getStringExtra("msg");  
    10.         Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();  
    11.     }  
    12.   
    13. }  

    (3)在Manifest.xml中注冊广播接收器:

    1. <receiver android:name=".MyReceiver">  
    2.         <intent-filter>  
    3.             <action android:name="ELITOR_CLOCK" />  
    4.         </intent-filter>  
    5. </receiver>  

    二、Fragment的使用方法

      在Activity用Fragment替换之前已有的布局须要填充满的话。改动Fragment里面返回的布局。

    <pre name="code" class="java">	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)动态使用

    1.         FragmentManager fm = getFragmentManager();  
    2.         FragmentTransaction transaction = fm.beginTransaction(); 
    3.         mWeixin = new ContentFragment();
    4.         transaction.replace(R.id.id_content, mWeixin);   
    5.         transaction.addToBackStack(null); 
    6.         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会打印出很多套生命周期的回调。

    1. 07-20 08:18:46.651: E/FragmentOne(1633): onCreate  
    2. 07-20 08:18:46.651: E/FragmentOne(1633): onCreate  
    3. 07-20 08:18:46.651: E/FragmentOne(1633): onCreate  
    4. 07-20 08:18:46.681: E/FragmentOne(1633): onCreateView  
    5. 07-20 08:18:46.831: E/FragmentOne(1633): onCreateView  
    6. 07-20 08:18:46.891: E/FragmentOne(1633): onCreateView  
    这是为什么呢,由于当屏幕发生旋转。Activity发生又一次启动,默认的Activity中的Fragment也会跟着Activity又一次创建;这样造成当旋转的时候,本身存在的Fragment会又一次启动。然后当运行Activity的onCreate时,又会再次实例化一个新的Fragment,这就是出现的原因。

    那么怎样解决呢:

    事实上通过检查onCreate的參数Bundle savedInstanceState就能够推断,当前是否发生Activity的又一次创建:

    默认的savedInstanceState会存储一些数据,包含Fragment的实例:通过打印能够看出:

    1. 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}]}]  
    1. 所以。我们简单改一下代码,仅仅有在savedInstanceState==null时,才进行创建Fragment实例:
    1. package com.zhy.zhy_fragments;  
    2.   
    3. import android.app.Activity;  
    4. import android.app.FragmentManager;  
    5. import android.app.FragmentTransaction;  
    6. import android.os.Bundle;  
    7. import android.util.Log;  
    8. import android.view.Window;  
    9.   
    10. public class MainActivity extends Activity  
    11.   
    12. {  
    13.     private static final String TAG = "FragmentOne";  
    14.     private FragmentOne mFOne;  
    15.   
    16.     @Override  
    17.     protected void onCreate(Bundle savedInstanceState)  
    18.     {  
    19.         super.onCreate(savedInstanceState);  
    20.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
    21.         setContentView(R.layout.activity_main);  
    22.   
    23.         Log.e(TAG, savedInstanceState+"");  
    24.           
    25.         if(savedInstanceState == null)  
    26.         {  
    27.             mFOne = new FragmentOne();  
    28.             FragmentManager fm = getFragmentManager();  
    29.             FragmentTransaction tx = fm.beginTransaction();  
    30.             tx.add(R.id.id_content, mFOne, "ONE");  
    31.             tx.commit();  
    32.         }  
    33.           
    34.           
    35.   
    36.     }  
    37.   
    38. }  

    如今不管进行多次旋转都仅仅会有一个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<ResolveInfo> 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);</span>












  • 相关阅读:
    02 日志系统: 一条SQL 更新语句是如何执行的
    MySql 实战45讲笔记 : 01
    爬取boss直聘全国招聘数据并做可视化
    爬取豆瓣电影-长津湖短评
    尝试破解压缩文件
    将webp格式的图像批量转化成jpg
    将JPG格式图片转换成PNG格式
    几个学习编程的游戏网站
    检测网址连接有效性
    监控设备电池电量并发送通知
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7357904.html
Copyright © 2020-2023  润新知