抓根宝

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

错误调试,由下至上,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>

图标略

 

posted on 2016-05-24 22:48  抓根宝  阅读(195)  评论(0编辑  收藏  举报