2.Activity启动模式+Intent+AsylncTask+ListView

一.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属性

     

           

           

     

注意: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

第一个参数:  子线程执行方法的参数类型,对应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中定义数组

                           

                           北京

                           

               step2:在listView中添加entries属性       

                          android:entries="@array/citys"

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

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

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

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

         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 map = new HashMap();

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+ListView)