布局、SD路径、单元测试、SQLitePC蛋蛋源码出租与ListView

相对PC蛋蛋源码出租 dsluntan.com Q:3393756370 VX:17061863513布局 RelativeLayout
组件默认左对齐、顶部对齐
设置组件在指定组件的右边
android:layout_toRightOf="@id/tv1"

设置在指定组件的下边
android:layout_below="@id/tv1"

设置右对齐父元素
android:layout_alignParentRight="true"

设置与指定组件右对齐
android:layout_alignRight="@id/tv1"

线性布局LinearLayout
指定各个节点的排列方向

设置右对齐
android:layout_gravity="right"

当竖直布局时,只能左右对齐和水平居中,顶部底部对齐竖直居中无效

当水平布局时,只能顶部底部对齐和竖直居中
使用match_parent时注意不要把其他组件顶出去
线性布局非常重要的一个属性:权重
android:layout_weight="1"
权重:按比例分配屏幕的剩余宽度或者高度
帧布局FrameLayout
默认组件都是左对齐和顶部对齐,每个组件相当于一个div
可以设置上下左右对齐,水平竖直居中,设置方式与线性布局一样
android:layout_gravity="bottom"

不能相对于其他组件布局

表格布局TableLayout
每个节点是一行,它的每个子节点是一列
表格布局中的节点可以不设置宽高,因为设置了也无效

根节点的子节点宽为匹配父元素,高为包裹内容
节点的子节点宽为包裹内容,高为包裹内容
以上默认属性无法修改
根节点中可以设置以下属性,表示让第1列拉伸填满屏幕宽度的剩余空间
android:stretchColumns="1"

绝对布局AbsoluteLayout
直接指定组件的x、y坐标
android:layout_x="144dp"
android:layout_y="154dp"
注意:直接复制项目需要改动的地方:项目名字、应用包名、R文件重新导包

路径API说明
getFilesDir()得到的file对象的路径是data/data/应用包名/files
存放在这个路径下的文件,只要你不删,它就一直在
getCacheDir()得到的file对象的路径是data/data应用包名/cache

存放在这个路径下的文件,当内存不足时,有可能被删除
系统管理应用界面的清除缓存,会清除cache文件夹下的东西,清除数据,会清除整个包名目录下的东西

sd卡的路径
2.2之前,sd卡路径:sdcard
4.3之前,sd卡路径:mnt/sdcard
4.3开始,sd卡路径:storage/sdcard

最简单的打开sd卡的方式
File file = new File("sdcard/test.txt");

使用api获得sd卡的真实路径,部分手机品牌会更改sd卡的路径
Environment.getExternalStorageDirectory()

判断sd卡是否准备就绪
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))

获取SD容量
import java.io.File;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.StatFs;
import android.text.format.Formatter;
import android.widget.TextView;

public class MainActivity extends Activity {
private TextView tv;br/>@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
if(existSDCard()){
String available = formatSize(getAvailable());
String allSize = this.formatSize(getAllSize());
tv.setText("总空间:"+allSize+" 可用空间"+available);
}
}

//获取可用容量
private long getAvailable(){
    File path = Environment.getExternalStorageDirectory();
    StatFs sf = new StatFs(path.getPath());
    //获取单个数据块的大小(Byte)
    long blockSize = sf.getBlockSizeLong();
    //获取所有数据块数
    long availbleBlocks = sf.getAvailableBlocksLong();
    return blockSize* availbleBlocks;
}

//获取总容量
private long getAllSize(){
    File path = Environment.getExternalStorageDirectory();
    StatFs sf = new StatFs(path.getPath());
    //获取单个数据块的大小(Byte)
    long blockSize = sf.getBlockSizeLong();
    //获取所有数据块数
    long allBlocks = sf.getBlockCountLong();
    return blockSize*allBlocks;
}

//格式化函数
private String formatSize(long size) {
    return Formatter.formatFileSize(this, size);
}

//是否挂载SD卡
private boolean existSDCard() {
    if (Environment.getExternalStorageState().equals(
            Environment.MEDIA_MOUNTED)) {
        return true;
    } else return false;
}

}
注意:在使用getBlockCountLong()等API的时候主要SDK的版本,SDK17是不支持getBlockCountLong()的,低版本的SDK仍然使用getBlockCount()等不带Long的
这里写图片描述

测试
测试分类
黑盒测试
测试逻辑业务
白盒测试

测试逻辑方法
根据测试粒度

方法测试:function test
单元测试:unit test
集成测试:integration test
系统测试:system test
根据测试暴力程度

冒烟测试:smoke test(例如monkey 1000:在屏幕上随机点击1000次)
压力测试:pressure test
Android中的单元测试
首先要使用一个类继承自AndroidTestCast:

import android.test.AndroidTestCase;

public class Test extends AndroidTestCase {
public void test(){
//TODO 测试的代码或者方法
}
}
并且在中做出如下配置:

<instrumentation android:name="android.test.InstrumentationTestRunner"android:allowBackup="true"
android:icon="@drawable/ic_launcher"
br/>android:targetPackage="要测试的应用包名">
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >

SQLite
轻量级关系型数据库
创建数据库需要使用的api:SQLiteOpenHelper
数据库被创建时会调用:onCreate方法
数据库升级时会调用:onUpgrade方法
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MyOpenHelper extends SQLiteOpenHelper {
public MyOpenHelper(Context context) {
//参数说明:上下文、数据库名称、游标工厂(默认使用NULL)、版本(用于升级)
super(context, "test.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
//创建表
db.execSQL("create table person(_id integer primary key autoincrement, name char(10), phone char(20), salary integer(10))");
}
//数据库升级的时候调用
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
System.out.println("数据库升级...");
}
}
创建数据库
//创建OpenHelper对象
MyOpenHelper oh = new MyOpenHelper(getContext(), "test.db", null, 1);
//获得数据库对象,如果数据库不存在,先创建数据库,后获得,如果存在,则直接获得
SQLiteDatabase db = oh.getWritableDatabase();
getWritableDatabase():打开可读写的数据库
getReadableDatabase():在磁盘空间不足时打开只读数据库,否则打开可读写数据库
数据库的增删改查
数据库的增删改查可以自己使用SQL语句,然后db.execSQL("SQL语句")即可完成!
注意:setup主要实现测试前的初始化工作,而teardown则主要实现测试完成后的垃圾回收等工作。
@Override
protected void setUp() throws Exception {
super.setUp();
//获取虚拟上下文对象
oh = new MyOpenHelper(getContext(), "test.db", null, 1);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
//关闭数据库
db.close();
}
使用API实现增删改查
//使用游标来逐个访问每条数据
public void select(){
Cursor cursor = db.rawQuery("select * from 表名", null);
//把指针移动至下一行
while(cursor.moveToNext()){
//先通过列名,获取列索引,然后再获取该列的内容
String str = cursor.getString(cursor.getColumnIndex("字段名1"));
String str2 = cursor.getString(cursor.getColumnIndex("字段名2"));
int str3 = cursor.getInt(cursor.getColumnIndex("字段名3"));
System.out.println(str+str2+str3);
}
}
public void insertApi(){
ContentValues values = new ContentValues();
values.put("字段1", "value");
values.put("字段2", "value");
values.put("字段3", "value");
//返回值-1,插入失败
long l = db.insert("表名", null, values);
}
public void deleteApi(){
//因为后面要传入的是对象数组
int i = db.delete("表名", "_id = ?", new String[]{"4"});
}
public void updateApi(){
ContentValues values = new ContentValues();
values.put("字段名", "value");
int i = db.update("表名", values, "_id = ?", new String[]{"1"});
}
事务
保证多条SQL语句要么同时成功,要么同时失败,失败的话会发生回滚!
public void transaction(){
try{
//开启事务
db.beginTransaction();
//TODO 修改表数据...
//设置事务执行成功,提交时如果这行代码没有执行过,就会回滚
db.setTransactionSuccessful();
}
catch (Exception e) {
//这里的异常必须要捕获
e.printStackTrace();
}
finally{
//关闭事务,提交数据
db.endTransaction();
}
}
ListView
用于显示列表
MVC结构
M:model模型层,要显示的数据 ————people集合
V:view视图层,用户看到的界面 ————ListView
c:control控制层,操作数据如何显示 ————adapter对象
每一个条目都是一个View对象
BaseAdapter
必须实现的两个方法
// 适配器类
class MyAdapter extends BaseAdapter {
// 系统调用:获取模型层数据的数量
@Override
public int getCount() {
return list.size();
}
// 系统调用:获取要显示至ListView的View对象
// convertView:系统之前缓存的条目
@Override
public View getView(int position, View convertView, ViewGroup parent) {
People p = list.get(position);
View view = null;
if (convertView == null) {
// 把布局文件填充为view对象(看源码,这就是三种方式)
// LayoutInflater layIn = LayoutInflater.from(MainActivity.this);
// LayoutInflater layIn = (LayoutInflater)getSystemService("layout_inflater");
// view = layIn.inflate(R.layout.item_listview,null);
view = View.inflate(getApplicationContext(),R.layout.item_listview, null);
} else {
view = convertView;
TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);
TextView tv_sa = (TextView) view.findViewById(R.id.tv_sa);
tv_name.setText(p.getName());
tv_phone.setText(p.getPhone());
tv_sa.setText(p.getSalary());
}
return view;
}
}
屏幕上能显示多少个条目,getView方法就会被调用多少次,屏幕向下滑动时,getView会继续被调用,创建更多的View对象显示至屏幕
条目的缓存
当条目划出屏幕时,系统会把该条目缓存至内存,当该条目再次进入屏幕,系统在重新调用getView时会把缓存的条目作为convertView参数传入,但是传入的条目不一定是之前被缓存的该条目,即系统有可能在调用getView方法获取第一个条目时,传入任意一个条目的缓存!
ArrayAdapter
在条目中显示一个字符串
String[] objects = new String[]{"AAA","BBB","CCC"};
ListView lv = (ListView) findViewById(R.id.lv);
//arg1:指定要填充的布局文件
//arg2:指定文本显示至哪一个文本框内
lv.setAdapter(new ArrayAdapter(this, R.layout.item_array, R.id.tv_name, objects));
SimpleAdapter
可在条目中显示多种数据
要显示的数据封装在List中,集合的每一个元素存放的是一个条目会显示的数据,因为可能会有多种数据,而集合的泛型只能指定一种数据,所以把数据先存放在Map中,在把Map放入List中
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView)findViewById(R.id.lv);
//把每个条目需要处理的所有数据封装至map中,在把map封装至list中
//这样就保证了list每个元素都包含了一个条目需要的所有数据
List> data = new ArrayList>();
Map m1 = new HashMap();
m1.put("name","AAA");
m1.put("Photo",R.drawable.a);
data.add(m1);
Map m2 = new HashMap();
m2.put("name","BBB");
m2.put("Photo",R.drawable.b);
data.add(m2);
Map m3 = new HashMap();
m3.put("name","CCC");
m3.put("Photo",R.drawable.c);
data.add(m3);
lv.setAdapter(new SimpleAdapter(MainActivity.this, data, R.layout.item_listview,
new String[]{"name","Photo"} ,
new int[]{R.id.name, R.id.iv}));

布局、SD路径、单元测试、SQLitePC蛋蛋源码出租与ListView

原文地址:http://blog.51cto.com/13916174/2156878

时间: 2024-11-05 20:49:25

布局、SD路径、单元测试、SQLitePC蛋蛋源码出租与ListView的相关文章

Retrofit2.0使用PC蛋蛋源码搭建姊妹篇——带进度下载文件

Retrofit是PC蛋蛋源码搭建 dsluntan.com 目前最主流的网络框架了,它对网络请求几近完美的封装,大大降低了我们开发者的研发难度,缩短了研发周期.最近项目中遇到了下载视频和图片文件的需求(还有上传视频和图片的需求,请移步这篇博客),我第一反应是用retrofit做呀,so easy!产品接着说,要带下载进度条哦!我一想,retrofit好像并没有给我们提供显示下载进度的接口,哎呀,看来还是得自己个儿整整喽!接下来,我把自己实现Retrofit带进度下载文件的流程分享给大家.在de

基于用户PC蛋蛋源码下载画像大数据的电商防刷架构

PC蛋蛋源码下载联系方式:QQ:2747044651 网址请添加链接描述最近1~2年电商行业飞速发展,各种创业公司犹如雨后春笋大量涌现,商家通过各种活动形式的补贴来获取用户.培养用户的消费习惯. 但任何一件事情都具有两面性,高额的补贴.优惠同时了也催生了"羊毛党". "羊毛党"的行为距离欺诈只有一步之遥,他们的存在严重破环了活动的目的,侵占了活动的资源,使得正常的用户享受不到活动的直接好处. 今天主要分享下腾讯自己是如何通过大数据.用户画像.建模来防止被刷.恶意撞库

游戏差异更新—PC蛋蛋源码下载BSDiff算法解析

PC蛋蛋源码下载联系方式:QQ:2747044651 网址请添加链接描述----pi2502差异更新即在软件更新时只更新差异化的部分,以达到用最小的下载量完成软件的更新需求.该思想由来已久,从刚接触电脑时的操作系统.应用软件快速更新功能或填补漏洞,到迭代更加频繁的移动应用时代更多了节省下载流量费用的需求.尤其在移动游戏领域,随着手机性能的提升和玩家对游戏体验的追求,安装包亦是越来越大,并且会频繁的更新以不断给玩家带来更新的玩法和更为优化的体验.然而,这种频繁的更新也同样会带来负面的影响:更新包太

利用ServerlessPC蛋蛋源码下载,让COS中文件变更自动刷新CDN

第二种是使用字段判断逻辑PC蛋蛋源码下载联系方式:QQ:2747044651 网址http://zhengtuwl.com .也就是服务器进程,会在每次读取缓存前,根据一些特征数据,快速的判断内存中的缓存和源数据内容,是否有不一致(是否脏)的地方,如果有不一致的地方,就自动清理这条数据的缓存.这种做法会消耗一部分CPU,但是就不需要人工去处理清理缓存的事情,自动化程度很高.现在我们的浏览器和WEB服务器之间,就有用这种机制:检查文件MD5:或者检查文件最后更新时间.具体的做法,就是每次浏览器发起

c/c++如何解决PC蛋蛋源码下载 大数存储问题(100的阶乘)

PC蛋蛋源码下载 联系方式:QQ:2747044651 网址http://zhengtuwl.com 首先在编程中会遇到一些很大的数,由于已经给定的数据类型存储范围有限,所以我们应该掌握,如何处理这样的问题. 我这里通过一个计算100!的例子给出思路. 想要存储100的阶乘,已有的数据类型肯定无法存储,我们可以使用字符串或者数组来解决,通过模拟基本计算过程,将 得到的数据存储到数组或字符串中保存下来.不多说先给出C语言解法! #include<stdio.h>#define max 1000i

如何避免DockerPC蛋蛋源码下载 容器启动脚本运行后自动退出—

docker build DocPC蛋蛋源码下载 联系方式:QQ:2747044651 网址http://zhengtuwl.com kerfile后,采用docker run --name xxx -d 运行容器,发现start.sh执行后容器就退出了,根本无法启动定时任务,网上各种办法有说用nohup,有死循环,还有说用信号,发现都不靠谱.分析了一下docker的机制,一个docker容器同时只能管理一个进程,这个进程退出后,容器也就退出了.这并不意味着一个容器里只能同时运行一个进程(那样太

青龙大厅源码出租Android的开发生态系统发展迅速

前言Android的开发生态系统发展迅速,在开发Android的几年的时间里,用来构建Android应用的架构与技术一直在不断进化.青龙大厅源码出租(h5.hxforum.com)企鹅2952777280 源码出售 房卡出售 后台出租随着项目的不断更新迭代,应用的架构也有不一样的变化.由于开发人员的数量.项目的业务复杂度.需求的开发时间.应用的使用量级,使用的技术架构也不相同.没有最好的架构,只有最合适的.通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发

利用python广西快乐十分源码出租爬取网易云歌手top50歌曲歌词

python广西快乐十分源码出租 dsluntan.com Q:3393756370 VX:17061863513近年来,发展迅速,成为了最炙手可热的语言. 那么如何来进行网易云歌手top50的歌曲歌词爬取呢 首先进行网易云并进行喜欢的歌手搜索如下: 在这里需要注意的是http://music.163.com/#/artist?id=1007170并不是真的我们需要的连接,真实的链接应该是http://music.163.com/artist?id=1007170 搞清楚了连接的问题之后,就要进

android 从源码分析为什么Listview初次显示时没滚动却自动调用onScroll方法的原因

我们做Listview的分批加载时,需要为Listview调用setOnScrollListener(具体代码可见我上一篇博客) 可是,我们会发现,当运行程序时,listview明明没有滚动,那为什么系统会调用onScroll方法呢?(补充:此时onScrollStateChanged并不会调用) 我们先看setOnScrollListener源码: public void setOnScrollListener(OnScrollListener l) { mOnScrollListener =