美文网首页
2.Activity启动模式+Intent+AsylncTask

2.Activity启动模式+Intent+AsylncTask

作者: chaohx | 来源:发表于2017-06-20 15:41 被阅读56次

    一.Activity的启动模式  两种方式四种模式

    (1)在清单文件中,标签中配置android:launchMode=""属性

         四个属性值:

         <1>standard:

                                默认的  可以实例化多次,每次启动都会创建一个新的实例

         <2>singleTop:

                                 可以实例化多次,当其在栈顶时,只能创建一个实例

                                 当栈顶存在要启动的Activity实例时,系统会调用onNewIntent()方法

                                 把Intent对象传递给已经存在的Activity实例,从而重用栈顶的Activity

          <3>singleTask:

                                    栈内部只能有一个Activity实例,

                                    解释一:当第二次启动该Activity时,系统会从上到下依次寻找该Activity已有的实例,

                                    找到会移除它之上的所有Activity实例,并重用该Activity实例

                                    解释二:当栈中存在要启动的Activity实例时,系统会调用onNewIntent() 方法

                                    把Intent对象传递给已经存在的Activity实例,从而重用该Activity实例

           <4>singleInstance:

                                    系统会单独分配一个任务栈,并把它的实例放到栈底,不和别的Activity共享一个栈

    (2)在Activity类中通过Intent对象设置启动模式,优先级高于上面的方式

            Intent intent = new Intent();

            intent.setFlags(Intent.参数);

    参数:

              默认                      等同于standard

              FLAG_ACTIVITY_SINGLE_TOP  等同于singleTop

              FLAG_ACTIVITY_CLEAR_TOP  等同于singleTask

              FLAG_ACTIVITY_NEW_TASK    等同于singleInstance

              如果是代码中设置启动模式:NEW_TASK,则必须在清单文件中加上下面属性

              android:taskAffinity="com.other"

              android:allowTaskReparenting="true"

              否则不起作用

    二.Intent七大属性

    (1)Intent的作用

          包装android的组件

          启动Activity ,启动Service,发送广播

         组件之间的传值

    (2)显示意图------setClass()

                         ------setComponent();

    明确指定要跳转到哪个Activity(通常用于启动应用内部的Activity)

    写法一: Intent intent = new Intent(MainActivity.this,InfoActivity.class);

    写法二: Intent intent= new Intent();

                     intent.setClass(MainActivity.this,InfoActivity.class);

    写法三:  ComponentName 包装Android组件

                   Intent intent = new Intent();

                   ComponentName cn = new  ComponentName(MainActivity.this,InfoActivity.class);

                   intent.setComponent(cn);

    (3)隐身意图------action      

         不明确指定目标Activity,而是通过Intent的动作action(通常用于多个应用程序之间的跳转)      

         必须在android应用中保持唯一      

        目标Activity中必须声明action属性

         <intent-filter>

               <action   android:name="com.qf.day06_lunchmode.CActivity"/>

               <category  android.intent.category.DEFAULT"/>

         </intent-filter>

    注意:action属性一般需要和category属性一起使用

    访问者:

    方式一: Intent intent=new  Intent();

                    Intent();intent.setAction("com.qf.day06_lunchmode.CActivity");        

    方式二:                

                  Intent intent  = new Intent("com.qf.day06_lunchmode.CActivity");                     

                  android.setting.SETTINGS 设置页面

                  Intent.ACTION_DIAL      拨号页面

                  Intent.ACTION_CALL      拨打电话(直接呼出)

    (4)category:表示action组件启动的类型

                一般android.intent.category.DEFAULT 代表普通的Activity组件

    (5)data属性:指定action后,将必须的属性设置在此属性中

              如:打电话  必须提供电话号码

                   打开网页    网址

             URI  统一资源标识

                     打电话: tel:53435343443

                     发短信: smsto:760439045

                     网址:  http://www.baidu.com

    (6)type属性:

               如果data属性是文件的路径,必须通过type来指定文件的类型

               图片:  image/*

               文本:  text/*

               视频:  video/*

               音频:  audio/*

    (7)extra 属性:除了必须的属性之外的扩展信息的属性

                  常用于Android组件之间传递数据

    (8)flag:组件的启动模式 (参考Activity的启动模式)

                广播接收器,启动Activity组件式,必须指定flag属

               性:FLAG_ACTIVITY_NEW_TASK

    三.AsyncTask的使用

    (1)定义一个类,继承AsyncTask类,同时声明三个泛型      

    public class MyAsyncTask extends AsyncTask<String,Integer,Byte[]>

    第一个参数:  子线程执行方法的参数类型,对应doinbackground的参数

    第二个参数:  子线程执行方法的进度,    对应onProgressUpdate的参数  可以为空,Void首字母应该大写

    第三个参数:  子线程执行任务的结果返回类型,对应onPostExecute的参数和doInbackground的返回值

    (2)AsyncTask的四个核心方法(重写)

            //运行在主线程中,执行异步任务时,首先调用的方法,用于初始化

           <1>protected void onPreExecute()//运行在子线程中,执行耗时的操作(后台线程)

           <2>protected byte[] doInBackground(String... params)//运行在主线程中,用于更新                                                                                                       进度,更新前必须先手动                                                                                                         调用publishProgress()方                                                                                                          法

          <3>protected void onProgressUpdate(Integer...values)//运行在主线程中,在                                                                                                                   doInbackground方法之后                                                                                                       执行,系统自动调用

          <4>protected void onPostExecute(byte[] result)

    (3)利用回调接口来实时更新进度

    <1>定义一个回调接口

           public interface CallBack{

                         public void callBack(int progress);回调方法,参数为进度的百分比

           }

    <2>在访问网络的工具中声明回调接口(HttpUtils工具类)

    public  static String getJson(String path,CallBack callback){//以加载json字符串为例

              //获取网络资源的代码

             //调用CallBack接口中的回调方法传回进度

             callback.callBack(progress);

    }

    <3>在doInBackground方法中调用getJson方法,同实例化一个CallBack接口的匿名内部类

    protected byte[] donInBackground(String ... params){

               HttpUtils.getJson(params[0],new CallBack(){

                                public void callBack(int progress){

                                       //当获取网络资源的代码中调用此回调接口时,触发此处代码,并                                        传回进度

                                      //拿到进度值,更新进度条

                                    publishProgress(progress); //该方法将触发                                                                                                                    onProgressUpdate(Integer..values);方法

                                }

                 });

    }

    (4)取消异步任务

            (1)调用task.cancel(true);//true表示暴力取消,false温柔取消

            (2)温柔取消时系统会自动执行onCancelled()方法

                  protected void onCancelled() {

                                 if(isCancelled()){

                                     Toast.makeText(MainActivity.this, "任务被取消!",                                                                                                          Toast.LENGTH_LONG).show();

                                 }

                  }

    四.ListView的总结

    (1)主要属性:

                      android:divider = "#rgb"  Item之间的分割线的颜色,也可以是一张图片

                      android:dividerHeight = "1dp" Item之间的距离,通常为1dp

                      android:entries="@array/name"  用数组填充Item

    (2)填充方式:      

             <1>属性填充:          

                    step1:先在strings.xml中定义数组

                               <string_array name="citys">

                               <item>北京</item>

                               </string_array>

                   step2:在listView中添加entries属性       

                              android:entries="@array/citys"

               <2>在Activity中通过适配器填充          

                     ①ArrayAdapter填充,适用于Item中只有一个文本    数据源为:List<String>

                     ②SimpleAdapter填充,可以实现图文混排的效果,但图片必须是本地的(不能是从网络获取的)    数据源为:List<Map<String,Object>>

     ③自定义Adapter,创建自己的Adapter类继承BaseAdapter抽象类,实现抽象方法    数据源为:List<Map<String,Object>>或者ListM<javaBean>

             Step1:定义一个类继承BaseAdapter

             Step2:实现四个抽象方法

                         getCount()得到数据源的总长度

                         getItem(int position)得到下标对应的Item

                         getItemId(int position)得到下标对应的Item的Id

                         getView(int position,View convertView,ViewGrioup parent)

              step3:在getView方法中为每个Item配置布局和数据

    (3)ListView的事件监听器

             ①Item单击响应事件

                 OnItemClickListener

             ②Item长按响应事件

                 OnItemLongClickListener

             ③ListView滚动事件

                  listview.setOnScrollListener(new OnScroolListener()){

                         //该方法监听listView滚动状态的改变

                         //AbsListView ----- listView

                         //int scrollState----滚动的状态

                         //三种滚动状态对应三个状态码

                        //OnScrollListener.SCROLL_STATE_TOUCH_SCROLL------1 listView正                       在滑动且手指还在屏幕上

                        //OnScrollListener.SCROLL_STATE_FLING --------2  listView惯性滑动

                        //OnScrollListener.SCROLL_STATE_IDLE  --------0  listView停止滑动

                       public void onScrollStateChanged(AbsListView view,int scrollState){

                       }

                       //该方法监听listView滚动的方法

                       //AbslistView view------listView

                      //int firstVisibleItem ------当前屏幕最上方显示的Item的下标

                      //int visibleItemCount ------当前屏幕显示Item的个数,半个也算

                      //int totalItemCount  -------当前所有Item的总数

                      public void onScroll(AbsListView view,int firstVisibleItem,

                                                                    int visibleItemCount,int totalItemCount){

                                  //小技巧:判断是否滑动到最底部

                                 Boolean islast = (firstVisible+visibleItemCount==totalItemCount);

                      }

    }

    (4)ListView 的优化

    ①属性优化:

                        android:layout_width="match_parent"

                        android:layout_height="match_parent"

                         如果是wrap_content,加载时每条Item会执行多次来计算ListView的宽高

    ②重用convertView对象,将Item布局缓存起来从而复用

    ③定义ViewHolder类,减少findViewById的次数

    参考代码:

    public View getView(int position, View convertView, ViewGroup parent) {

                        ViewHolder holder;

                        if (convertView == null) {

                                           holder = new ViewHolder();

                                           convertView = View.inflate(context, R.layout.item_listview, null);

                                           holder.textViewName = (TextView)                                                                                                                     convertView.findViewById(R.id.name);

                                            holder.textViewDescription = (TextView)                                                                                                          convertView.findViewById(R.id.description);

                                           convertView.setTag(holder);

                           } else {

                                            holder = (ViewHolder) convertView.getTag();

                          }

                          holder.textViewName.setText(list.get(position).getName());

                          holder.textViewDescription.setText(list.get(position).getDescription());

                          return convertView;

    }

    (5)ListView加载网络图片,实现图文混排

    通常图片地址在Json数据中或者XML文件中.(以json为例)

    <1>通过网络加载json数据,然后解析封装成类

    <2>在ListView的Adapter中构建Item时,

    如果是文本内容则直接设置,如果为图片内容则开启异步任务去网络中加载

    <3>对加载好的图片进行缓存,当第二次需要展示的时候,直接在内存中加载而不用访问网络

    此处用Map来缓存(只是模拟),其他缓存方式后续更新

    <4>由于convertView的复用,和异步任务形成的时间差,会造成图片错位现象

    通过为ImageView打标签可以解决图片错位的问题

    代码:  

    Map<String,Bitmap> map = new HashMap<String,Bitmap>();

    ViewHolder holder;

    public View getView(int position, View convertView, ViewGroup parent) {

                if (convertView == null) {

                                holder = new ViewHolder();

                                convertView = View.inflate(context, R.layout.item_listview, null);

                                holder.imageView = (ImageView)                                                                                                              convertView.findViewById(R.id.image);

                                holder.textViewName = (TextView) convertView

                                                                                .findViewById(R.id.name);

                                convertView.setTag(holder);

                   } else {

                                 holder = (ViewHolder) convertView.getTag();

                   }

                   holder.imageView.setImageResource(R.drawable.ic_launcher);//用于清空被                                                                                             重用的holder中携带的图片内容

                   String curImageUrl = list.get(position).getCoverUrl();

                   holder.imageView.setTag(curImageUrl);//为ImageView打标签,用此                                                                                                imageView要显示图片的地址最为标签

                   if (!map.containsKey(curImageUrl)) {//判断Map中是否存有该地址(图片资源)

                             //如果Map中没有缓存,说明是第一次加载此图片,需要从网络获取

                             new ImageAsyncTask(new CallBack() {//开启异步任务加载图片

                                          @Override

                                           public void callBack(String path, Bitmap bitmap) {

                                                         //通过回调方法返回加载图片资源和其地址

                                                        //将加载好的图片资源和地址存入Map进行缓存

                                                        map.put(path, bitmap);

                                                        ImageView imageView = (ImageView)                                                                                                                     listView.findViewWithTag(path);

                                                        //通过标签在ListView中找到对应的imageView,并为其                                                        设置图片资源

                                                       if (imageView != null) {

                                                                         imageView.setImageBitmap(bitmap);

                                                       }

                                               }

                                      }).execute(curImageUrl);

                      } else {

                                  //如果Map中缓存的有需要的图片,则直接拿过来使用

                                   holder.imageView.setImageBitmap(map.get(curImageUrl));

                   }

                   holder.textViewName.setText(list.get(position).getName());

                    return convertView;

    }

    class ViewHolder {

                        ImageView imageView;

                       TextView textViewName;

    }

    相关文章

      网友评论

          本文标题:2.Activity启动模式+Intent+AsylncTask

          本文链接:https://www.haomeiwen.com/subject/pjaoqxtx.html