柚子快报邀请码778899分享:安卓零碎知识集中

http://www.51969.com/

       因为安卓的知识点较多。平时动看看西看看,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分享:安卓零碎知识集中

http://www.51969.com/

查看原文