zoukankan      html  css  js  c++  java
  • Android开发04

    错误调试,由下至上,CausedBy(然后并没有找到) 里面出现的java异常,在这个异常下面找自己的类中出现的问题,双击可以打开对应的位置

    在上一篇笔记中,引入了ListView控件

    但是在使用的时候,ListView控件里拖动太快就容易导致内存溢出(条目足够多的情况下)不断拖动,就会不断创建对象,然而垃圾回收器这个时候如果还没有进行回收的话,就一样会导致程序内存溢出,然后崩溃.

    ListViewgetView方法的四个参数

    Int Position 当前View控件的条目数

    View covertView 一个用来复用的View

    编写代码的时候,就可以通过复用View来避免不断创建对象,这样就不会内存溢出了,而是一直在使用被回收的View

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

    TextView tv =null;

    if(convertView==null){

    tv = new TextView(MainActivity.this);

    }else{

    tv = (TextView) convertView;

    }

    tv.setText(students.get(position).toString());

    return tv;

    }

    2,采用打气筒创建view对象

    2.1原因:原来的样式不好看,要更好看的样式.如果直接通过代码创建一个控件,再创建子控件,设置背景颜色,图片,文字等等,这样的话比较麻烦(其实就是懒,个人感觉挺好创建的,不过对代码要更熟悉一点),所以google提供了一个api来引用外部的xml样式文件来达到这一效果.

    创建的xml文件相当于一个气球,使用打气筒View.inflate(context,resource(资源文件),root(代表气球所处的位置,通常为null))(把一个 xml文件转换成View对象)就可以用了.

    注意:在匿名内部类中使用findViewById()的时候,使用的可能是MainActivity里面的方法(它获取到的id在它对应的xml文件中),而不是前面使用inlate获得的view对象对应的xml文件,所以获得的id对象可能不一样

    inflate转换的view 对象,底层也是用的pull解析,所有的布局文件都是通过转换成view对象,add到页面之上的.

    2.2  因为这个listView很重要,所以重复一遍步骤

    ,在布局xml文件中声明listView控件

    ,java 代码中找到ListView并且创建适配器

    ,getCount()来确定listView中条目的数量

    ,getView()返回某个位置显示的view对象

    View.inflate()打气筒可以把xml文件转换成view去显示

    android:layout_marginLeft属性,距离左边一个控件的距离

    2.3 其它事项:①添加一个图标显示删除按钮

    ②删除之后会跳到第0条记录,因为每次调用显示功能都相当于创建了一个新的适配器,所以会回到最开始的位置;

    解决方案:

    不能使用匿名内部类去做显示功能,要单独提取出来,创建一个类去实现BaseAdapter)

    //通知数据适配器更新数据,而不是new出来新的适配器(创建一个适配器,判断它是否为空)

    使用adapter.notifyDataSetChanged(),底层会先调用getCount方法,

    ListView.setSelection(条目数)设置对应的条目显示位置

    ③通过在onCreate方法中直接定义条目的点击删除方法

    Listview.setOnItemClickListener() 条目点击事件(是整个条目,而不是单个控件)

    Listview.setOnItemLongClickListenter()长按条目触发的事件

    mov平滑啥的,没记住

    ④封装ListView中的控件,面向Holder编程(未封装前每次创建convertView都会加载一次控件,通过封装控件来提高效率,节约控件)(找时间做)

    convertView.setTag(obj)可以储存对象(这个对象里封装控件)

         getTag()可以获得对象,(记得要强转,但是多个对象被储存了该怎么取出来?怎么判断)

    //作用,当第一次使用的时候,就把对象创建出来,convertView被重复使用的时候,就不用重复创建子控件对象

    3,消息框

    3.1 创建一个对话框,谷歌采用了工厂类的设计模式

    AlertDialog.Builder builder = new Builder(this);

    //设置消息框的名称

    builder.setTitle(“警告”);

    //提示文本

    builder.setMessage(“XXXXXX”);

    //设置确定取消按钮

    builder.setPositiveButton(“确定”,new OnclickListener())

    //取消对话框

    builder.setNegativeButton(“取消”,点击事件)

    //创建一个警告的对话框

    AlertDialog dialog = Builder.create();

    Dialog.show();

    3.2//单选对话框

    AlertDialog.Builder builder = new Builder(this);

    builder.setTitle(“文本”);

    Final String items=(x,x,x);

    builder.setSingleChoiceItems(items,默认性别(索引,-1什么都不选),点击事件);

    //取消对话框

    builder.setNegativeButton(“取消”,null);

    Builder.show(); (AlertDialog dialog = Builder.create();

    Dialog.show();

    )这两个方法的封装

    3.3//多选对话框

    AlertDialog.Builder builder = new Builder(this);

    //设置对话框的名称

    builder.setTitle(“文本”);

    String [] items = {x,x,x};

    Boolean [] checked={x,x,x};

    builder.setMultiChoiceItems(items,默认选项(通过checked布尔类型数组来确定),点击事件);

    点击事件中重写方法有一个isChecked变量,用来传入是否被点击,记得要给对应的选项状态重新赋值,不然一直都是初始状态

    3.4//取消对话框

    builder.setNegativeButton(“取消”,null);

    Builder.show();

    3.5//特殊对话框-等待对话框

    ProgressDialog pd =new ProgressDialog(this);

    pd.setTitle(“提醒”);

    pd.setMessage( “正在加载数据....稍后”);

    Pd.show();

    //关闭方法

    Ps.dismiss();

    3.6//进度条对话框

    ProgressDialog pd =new ProgressDialog(this);

    //设置进度显示方式,默认旋转的弧线

    pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

    //设置长度

    pt.setMAX(100);

    pd.setTitle(“提醒”);

    pd.setMessage( “正在加载数据....稍后”);

    Pd.show();

    //设置进度条进度

    pd.setProgress(数字,不大于长度);

    //关闭方法

    Ps.dismiss();

    注意builder设置单击事件的时候注意导包

    ListView属性:fastScrollEnable 快速进度条,可以直接拖动到末尾

    额外:姓名去重,遍历已经存在的姓名,如果姓名已经存在,就提示是否覆盖(消息框)

    4,谷歌封装的SQL语句的API(谷歌封装的,并不是原生的,所以要注意,不要把sql语句给荒废了)

    SQLiteDatabase db = helper.getWritableDatabase();

    4.1

    db.insert(表名,null,ContentValues);(本方法底层就是SQL语句的添加操作,并且带有返回值,返回添加到的行数,返回为-1就代表没有添加成功)

    第二个参数,当第三个为空的时候,第二个参数就为列名称,否则为null

    第三个参数底层是一个HashMap集合,键代表列名称,值代表具体的数据

    4.2

    db.delete(表格,where条件,选择条件的参数参数),返回代表删除的数量

    4.3

    db.update(表名,修改的新的数值(ContentValues),where条件,选择条件的参数,String数组);返回成功的数量,如果为0就代表没有修改成功

    4.4

    Cursro cursor = db.query(表名,获取的列数组,选择条件,选择条件对应的参数,是否分组,分组条件(Having条件),是否排序);

    5.数据库的事务

    5.1事务:保证一组操作要么同时成功(并不代表同时执行,但是保证结果同时出现),要么同时失败(例如银行转账,AB转账1000.A的账户就会扣除1000,B的增加1000,当这中间放生故障时,B的收账失败,A的转账也要失败)

    5.2数据库事务逻辑

    //使用场景:大数据量添加(因为通过临时文件像数据库添加数据是通过C语言实现的,效率更高,速度更快)

    保证操作结果的同步性

    db.beginTransaction();//开启事务

    Try{

    代码逻辑//这些逻辑先存放在临时文件中,之后遇到事务执行成功的逻辑,就会一次性全部添加到数据库中.

    db.setTransactionSuccessful();//设置事务执行成功

    }finally{

    db.endTransaction();//保证事务有开启有关闭,如果没有关闭的话,数据库会一直被锁定,其它操作就不能执行(或者说一直等待)

    }

    Db.close;

    6,数据适配器(ListView中提到过)

    常用的数据适配器(都继承了BaseAdapter适配器):

    6.1 ArrayAdapter 数组适配器

    //适用于纯文本

    String arr = new String[]{x.x.x.x.x};

    listview.setAdapter(new ArrayAdapter<String>(this,R.layout.对应的文件),String数组);

    //可以在ListView中显示一组条目(然后可以设置条目的点击事件,跳转到别的逻辑中)

    6.2 SimpleAdapter(上下文,参数二,布局文件,参数四,参数五)

    //使用场景,用于带图片条目的实现

    参数二:list<extends Map<x,x>> data = new ArrayList<Map<x,x>>();

    //一个泛型为Map集合的List集合

    每一个Map集合,可以用来储存一个图标

    Map1.put(“icon”,id);

    Map1.put(“name”,”名字”);

    最后记得添加到List集合中

    后面两个参数是映射关系,用来找到List集合中的数据对应的样式

    参数四: new String{“icon”,”name”}

    参数五:new int{R.id.v,R.id.v}

    注意!使用SimpleAdapter 创建的list,是不能通过notifyDataSetChanged 来更新的,因为SimpleAdapter 主要是用来创建静态的数据的列表,如果要实现动态更新数据,需要自己定义一个基于BaseAdapteradapter,然后通过notifyDataSetChanged 来更新list

    7,Android下的帧动画(一共一三种,帧动画,twee(view)动画,属性动画)

     7.1 步骤

    ,创建一个drawable文件夹用来实现动画,复制图片

    ,创建一个 xml文件 andimation-list类型

    ,创建item条目,对应复制的图片,设置闪动的频率

    ,创建一个图片控件,并找到它

    ,设置背景图片资源 img.setBackgroundResource( xml文件)(布局文件中配置属性也可以)

    ,转换成动画资源 AnimationDrawable anim = (AnimationDrawable)img.getBackground();

    ,开始播放 andim.start();

    注意,如果设置src属性(会优化处理),会在BackgroundResouce(不会)之上

    //具体代码

    XML文件中

    <!-- Animation frames are wheel0.png -- wheel5.png files inside the

     res/drawable/ folder -->

     <animation-list android:id="@+id/selected" android:oneshot="false">

    <!--duration 闪动的频率-->

        <item android:drawable="@drawable/wheel0" android:duration="50" />

        <item android:drawable="@drawable/wheel1" android:duration="50" />

        <item android:drawable="@drawable/wheel2" android:duration="50" />

        <item android:drawable="@drawable/wheel3" android:duration="50" />

        <item android:drawable="@drawable/wheel4" android:duration="50" />

        <item android:drawable="@drawable/wheel5" android:duration="50" />

     </animation-list>

    //代码

     ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);

    //设置背景图片资源

     img.setBackgroundResource(R.drawable.spin_animation);

    //转换成动画资源

     AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();

    //开始播放动画

     frameAnimation.start();

    8,应用程序的国际化(非常非常的简单)

    I18n(国际化18个单词的简写,可用于创建包名)

    8.1,创建一个values-en文件夹,代表英文环境下的app字符串显示(不需要去获取手机使用的语言环境,Android会根据不同的语言环境获取对应的values-xx下的String.xml文件)

    文字的国际化

    如果不记得语言简写(百度)

    8.2使用这种方法实现的国际化,在布局文件中创建控件的文本属性时使用@String/文本值,就可以在不同语言环境下显示不同的文本.

    在代码中需要使用字符串的地方通过getResources().getString(R.String.XXX)获取字符串.

    图片的国际化:把对应国家的图片放在对应的values-XX文件夹下,图片名一致(不然设置图片的时候还要进行判断,简化一下更方便)

    8.3把字符串抽取出来的好处:方便后期维护,便于查找.

    9.样式和主题(样式的配置都可以通过代码实现)

    注意 定义自定义样式需要定义item属性,名称是对应的背景,文字名,文本值是对应的值

    <item name=”android:layout_width”>match_parent</item>

    9.1

    样式的定义:styles.xml(values文件夹下)定义属性style标签,把属性定义在里面,记得给style设置名字(才能在控件中使用);

    样式的使用:在需要使用的控件中定义style属性,指向定义的样式(R.style.xxx)

    作用范围:在控件上style

    9.2

    主题和样式没有绝对的区别,作用范围不一样

    作用范围: 作用在Activity,theme属性

    定义一个主题,styles.xml,定义style标签,name属性 在清单中查找的标识

    在清单文件下application定义theme属性指向对应的style标签

    9.3 样式的继承

    创建一个新的style属性,定义name属性,定义parent=”@style/XXX”>

    可以自定义属性替换父样式的属性,其它属性可以继承

    已经被废弃的写法(需要了解知道)

    style属性中写 name =”text_content_style_sub” 会继承text_content_style的样式.

    附上楼主自己写的学生MainActivity页面练习代码,数据库的crud比较简单,就不贴出来了

    package com.zzx.student;
    
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.AlertDialog.Builder;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.graphics.drawable.AnimationDrawable;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.ListView;
    import android.widget.RadioGroup;
    import android.widget.SimpleAdapter;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.zzx.student.db.dao.MyDBImp;
    import com.zzx.student.domain.Student;
    
    public class MainActivity extends Activity {
        //拿到需要的控件
        private ImageView iv_title;
        private EditText et_name;
        private RadioGroup rg_sex;
        private Button bt_sub;
        private ListView lv_show;
        private MyDBImp mdb ;
        private List<Student> students;
        private MyAdapter ma;
        private List< Map<String, Object>> list;
        private Map<String,Object> map;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //初始化控件
            initView();
            //设置帧动画
            showAnimation();
            //设置单击事件
            setOnClick();
            //显示事件
            showAll();
        }
        /**
         * 这里用来显示所有学生信息
         */
        private void showAll() {
            students = mdb.findall();
                list = new LinkedList<Map<String,Object>>();
                //遍历students集合
                for(Student s :students){
                    map = new HashMap<String, Object>();
                    String sex = s.getSex();
                    int a ;
                    //判断性别的图片
                    if("男".equals(sex)){
                        a = R.drawable.man;
                    }else{
                        a = R.drawable.woman;
                    }
                    //添加信息
                    map.put("sex", a);
                    map.put("name", s.getName());
                    map.put("delete", R.drawable.no_signal_96dp);
                    //添加进集合
                    list.add(map);
                }
            //把自定义适配器抽取成私有的,方便优化代码
            ma = new MyAdapter(MainActivity.this, list, R.layout.simpleadapter, new String[]{"sex","name","delete"}, new int[]{R.id.show_sex,R.id.show_name,R.id.d_m});
            lv_show.setAdapter(ma);
            lv_show.setSelection(10);
            
        }
        /**
         * 这是一个自定义适配器类
         * @author msi
         *
         */
        class MyAdapter extends SimpleAdapter{
    
            public MyAdapter(Context context, List<? extends Map<String, ?>> data,
                    int resource, String[] from, int[] to) {
                super(context, data, resource, from, to);
            }
            
        }
        
        /**
         * 这个方法用来设置listView的删除事件
         */
        public void deleteMe(View view){
            //设置警告信息
            AlertDialog.Builder adb = new Builder(MainActivity.this);
            adb.setTitle("警告");
            //找到父控件,通过父控件找到子控件,获取要删除的信息
            View vp = (View) view.getParent();
            final String name = ((TextView)vp.findViewById(R.id.show_name)).getText().toString();
            adb.setMessage("您是否要删除" + name + "的信息");
            adb.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(MainActivity.this, "删除成功", 0).show();
                    mdb.delete(name);
                    //刷新一下界面
                    showAll(); 
                }
            });
            //取消操作
            adb.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(MainActivity.this, "取消成功", 0).show();
                }
            });
            adb.show();
        }
        /**
         * //设置保存信息事件
         */
        private void setOnClick() {
            
            bt_sub.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    String name = et_name.getText().toString().trim();
                    //判断姓名是否为空
                    if(TextUtils.isEmpty(name)){
                        Toast.makeText(MainActivity.this, "姓名不能为空", 0).show();
                        return;
                    }
                    //获取性别
                    String sex = "男";
                    switch (rg_sex.getCheckedRadioButtonId()) {
                    case R.id.rb_man:
                        sex = "男";
                        break ;
                    case R.id.rb_woman:
                        sex = "女";
                        break;
                    }
                    Toast.makeText(MainActivity.this, "添加成功", 0).show();
                    //添加进数据库,
                    mdb.add(name, sex);
                    showAll();
                }
    
            });
        }
        /**
         * 这个方法用来做标题动画效果
         */
        private void showAnimation() {
            iv_title.setBackgroundResource(R.drawable.myantimation);
            //转换成动画资源
            AnimationDrawable anim = (AnimationDrawable) iv_title.getBackground();
            //开始播放
            anim.start();
        }
        /**
         * 初始化控件
         */
        private void initView() {
            iv_title = (ImageView) findViewById(R.id.imgtitle);
            et_name = (EditText) findViewById(R.id.ed_name);
            rg_sex = (RadioGroup) findViewById(R.id.rg_sex);
            bt_sub = (Button) findViewById(R.id.submit);
            lv_show = (ListView) findViewById(R.id.lv_showall);
            mdb = new MyDBImp(MainActivity.this);
        }
    
        
    }

    xml布局

    <LinearLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
    
        <ImageView 
            android:id="@+id/imgtitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
         <EditText
            android:id="@+id/ed_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="@string/studentname"
            android:textSize="22sp" />
        <TextView 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/selectsex"
            android:textSize="22sp"
            />
        <RadioGroup 
             android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/rg_sex"
            android:orientation="horizontal"
            >
                <RadioButton  
                      android:layout_width="0dp"
                      android:layout_weight="1"
                    android:layout_height="wrap_content"
                    android:text="@string/rb_man"
                    android:id="@+id/rb_man"
                    />
    
              
    
                  <RadioButton
                      android:id="@+id/rb_woman"
                      android:layout_width="0dp"
                      android:layout_weight="1"
                      android:layout_height="wrap_content"
                      android:text="@string/rb_woman" />
    
        </RadioGroup>
        <Button 
             android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:id="@+id/submit"
              android:text="@string/bt_sb" 
            />
        <ListView 
            android:fastScrollEnabled="true"
            android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:id="@+id/lv_showall"
            >
            
            
        </ListView>
    </LinearLayout>

    适配器布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" >
        
        <ImageView 
         android:id="@+id/show_sex"
        android:layout_width="30dp"
        android:layout_height="30dp"
                />
    
        <TextView
            android:id="@+id/show_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/show_sex"
            android:textSize="30dp" />
        
         <ImageView 
         android:layout_alignParentRight="true"
         android:id="@+id/d_m"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/no_signal_96dp"
        android:onClick="deleteMe"
            />
    
    
    </RelativeLayout>

    图标略

  • 相关阅读:
    windows安装php的redis扩展及测试(适合php个各个版本)
    golang+linux+pipline
    泰勒展开式
    微积分
    矩阵
    learning rate warmup实现
    python asyncio as_completed
    python asyncio run_until_complete
    python asyncio 使用ThreadPoolExecutor和asyncio完成阻塞IO请求
    python asyncio call_soon, call_at, call_later
  • 原文地址:https://www.cnblogs.com/adventurer/p/5525307.html
Copyright © 2011-2022 走看看