美文网首页
Android interview share2

Android interview share2

作者: hello_bin | 来源:发表于2017-03-23 16:54 被阅读53次
Android interview

-Android连接数据库

Android平台下与服务器数据库通信的方法主要有:
1、直接连接:在Android工程中引入jdbc驱动,采用驱动连接数据库;
2、间接连接:在服务器上用PHP+DBMS做服务器端,PHP将DBMS中的数据用JSON或者XML进行封装,然后将数据封装成接口,给Android平台回调。
 注意:采用jdbc方法主要问题是安全性不高,而且一旦需要访问的数据过多,容易出问题。另外,Android本身有对JSON或者XML数据直接解析的API,所以间接连接的方式更为可靠。

JDBC连接

JDBC是Java Data Base Connectivity的缩写,意思为“Java数据库连接”,由一组用Java语言编写的类和接口组成,为java层直接操作关系型数据库提供了标准的API。原理很简单,主要是先服务器DBMS发送SQL(结构化查询语言)指令。实现各种数据库的操作。
 在Android工程使用JDBC连接数据库的主要步骤:加载JDBC驱动程序------->建立连接--------->发送SQL语句。
 在项目中导入jdbc驱动,然后在代码开始出import jdbc的包。
  建立链接:每种DBMS的JDBC驱动是不一样的,同一个DBMS也会有几种JDBC驱动,如Microsoft SQL Server的JDBC驱动主要有两种,Microsoft 官方提供的JDBC驱动和民间开源的JDBC驱动(JTDS),推荐JTDS,bug少,而且是完全开放源代码的。目前JTDS只能支持Microsoft SQL Server和Sybase。
 由于DBMS与JDBC驱动的不同,所以每种JDBC连接数据库的字符串书写方法也是不一样的。 下面给出几种常见的JDBC与DBMS建立连接的字符串书写格式:

//1. MySQL(http://www.mysql.com)mm.mysql-2.0.2-bin.jar  
Connection con = null;  
Class.forName( "org.gjt.mm.mysql.Driver" );// 加载驱动程序  
con = DriverManager.getConnection( "jdbc:mysql://DbComputerNameOrIPAddr:3306/DatabaseName", UserName, Password );  
//2. PostgreSQL(http://www.de.postgresql.org)pgjdbc2.jar  
Connection con = null;  
Class.forName( "org.postgresql.Driver" );// 加载驱动程序  
con = DriverManager.getConnection( "jdbc:postgresql://DbComputerNameOrIPAddr/DatabaseName", UserName, Password );  
//3. Oracle(http://www.oracle.com/ip/deploy/database/oracle9i/)classes12.zip  
Connection con = null;  
Class.forName( "oracle.jdbc.driver.OracleDriver" );// 加载驱动程序  
con = DriverManager.getConnection( "jdbc:oracle:thin:@DbComputerNameOrIPAddr:1521:DatabaseName", UserName, Password );  
//4. Sybase(http://jtds.sourceforge.net)jconn2.jar  
Connection con = null;  
Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" );// 加载驱动程序  
con = DriverManager.getConnection( "jdbc:sybase:Tds:DbComputerNameOrIPAddr:2638/DatabaseName", UserName, Password );  
//(Default-Username/Password: "dba"/"sql")  
//5. Microsoft SQLServer(http://jtds.sourceforge.net)  
Connection con = null;  
Class.forName( "net.sourceforge.jtds.jdbc.Driver" );// 加载驱动程序  
con = DriverManager.getConnection( "jdbc:jtds:sqlserver://DbComputerNameOrIPAddr:1433/DatabaseName", UserName, Password );   
//6. Microsoft SQLServer(http://www.microsoft.com)  
Connection con = null;  
Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" );// 加载驱动程序  
con = DriverManager.getConnection( "jdbc:microsoft:sqlserver://DbComputerNameOrIPAddr:1433;databaseName=master", UserName, Password );

发送SQL语句(以SQL server为例),当成功连接数据库之后,就可以发送操作数据的语句并处理结果了。在发送SQL语句之前,首先要创建一个statement对象,statement对象主要工作是把SQL语句发送到DBMS。然后发送SQL语句。对于SELECT操作,使用的是Statement对象的executeQuery(sql )方法,对于一些创建table和修改table的操作,使用的是Statement对象的executeUpdate(sql )方法。

//查询表名为“table_test”的所有内容  
String sql = "SELECT * FROM table_test";
//创建Statement 
Statement stmt = con.createStatement(); 
ResultSet rs = stmt.executeQuery(sql);  

接口回调

调用自己服务器接口返回的数据,需要提供服务器地址,然后通过网络通信技术解析服务器返回的数据。

-Android图片处理、图片缓存机制

说到图片处理,我们得重点学习一下两个类:Bitmap、BitmapFactory。
Bitmap
 Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。

重要函数

public void recycle() // 回收位图占用的内存空间,把位图标记为Dead
public final boolean isRecycled() //判断位图内存是否已释放  
public final int getWidth()//获取位图的宽度 
public final int getHeight()//获取位图的高度
public final boolean isMutable()//图片是否可修改 
public int getScaledWidth(Canvas canvas)//获取指定密度转换后的图像的宽度 
public int getScaledHeight(Canvas canvas)//获取指定密度转换后的图像的高度 
public boolean compress(CompressFormat format, int quality, OutputStream stream)//按指定的图片格式以及画质,将图片转换为输出流。 
format:Bitmap.CompressFormat.PNG或Bitmap.CompressFormat.JPEG 
quality:画质,0-100.0表示最低画质压缩,100以最高画质压缩。对于PNG等无损格式的图片,会忽略此项设置。
public static Bitmap createBitmap(Bitmap src) //以src为原图生成不可变得新图像 
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)//以src为原图,创建新的图像,指定新图像的高宽以及是否可变。 
public static Bitmap createBitmap(int width, int height, Config config)——创建指定格式、大小的位图 
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height)以source为原图,创建新的图片,指定起始坐标以及新图像的高宽。

BitmapFactory

 Option 参数类:
public boolean inJustDecodeBounds//如果设置为true,不获取图片,不分配内存,但会返回图片的高度宽度信息。
public int inSampleSize//图片缩放的倍数
public int outWidth//获取图片的宽度值
public int outHeight//获取图片的高度值 
public int inDensity//用于位图的像素压缩比 
public int inTargetDensity//用于目标位图的像素压缩比(要生成的位图) 
public byte[] inTempStorage //创建临时文件,将图片存储
public boolean inScaled//设置为true时进行图片压缩,从inDensity到inTargetDensity
public boolean inDither //如果为true,解码器尝试抖动解码
public Bitmap.Config inPreferredConfig //设置解码器
public String outMimeType //设置解码图像
public boolean inPurgeable//当存储Pixel的内存空间在系统内存不足时是否可以被回收
public boolean inInputShareable //inPurgeable为true情况下才生效,是否可以共享一个InputStream
public boolean inPreferQualityOverSpeed  //为true则优先保证Bitmap质量其次是解码速度
public boolean inMutable //配置Bitmap是否可以更改,比如:在Bitmap上隔几个像素加一条线段
public int inScreenDensity //当前屏幕的像素密度

工厂方法:
public static Bitmap decodeFile(String pathName, Options opts) //从文件读取图片 
public static Bitmap decodeFile(String pathName)
public static Bitmap decodeStream(InputStream is) //从输入流读取图片
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts)
public static Bitmap decodeResource(Resources res, int id) //从资源文件读取图片
public static Bitmap decodeResource(Resources res, int id, Options opts) 
public static Bitmap decodeByteArray(byte[] data, int offset, int length) //从数组读取图片
public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts)
public static Bitmap decodeFileDescriptor(FileDescriptor fd)//从文件读取文件 与decodeFile不同的是这个直接调用JNI函数进行读取 效率比较高

枚举变量 (位图位数越高代表其可以存储的颜色信息越多,图像越逼真,占用内存越大)
public static final Bitmap.Config ALPHA_8 //代表8位Alpha位图        每个像素占用1byte内存
public static final Bitmap.Config ARGB_4444 //代表16位ARGB位图  每个像素占用2byte内存
public static final Bitmap.Config ARGB_8888 //代表32位ARGB位图  每个像素占用4byte内存
public static final Bitmap.Config RGB_565 //代表8位RGB位图          每个像素占用2byte内存

​ Android中一张图片(BitMap)占用的内存主要和以下几个因数有关:图片长度,图片宽度,单位像素占用的字节数。一张图片(BitMap)占用的内存 = 图片长度 ** 图片宽度 * * 单位像素占用的字节数。

下面列举几个常用方法的详细介绍:

/**
     * 获取缩放后的本地图片
     *
     * @param filePath 文件路径
     * @param width    宽
     * @param height   高
     * @return
     */
    public static Bitmap readBitmapFromFileDescriptor(String filePath, int width, int height) {
        try {
            FileInputStream fis = new FileInputStream(filePath);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFileDescriptor(fis.getFD(), null, options);
            float srcWidth = options.outWidth;
            float srcHeight = options.outHeight;
            int inSampleSize = 1;

            if (srcHeight > height || srcWidth > width) {
                if (srcWidth > srcHeight) {
                    inSampleSize = Math.round(srcHeight / height);
                } else {
                    inSampleSize = Math.round(srcWidth / width);
                }
            }

            options.inJustDecodeBounds = false;
            options.inSampleSize = inSampleSize;

            return BitmapFactory.decodeFileDescriptor(fis.getFD(), null, options);
        } catch (Exception ex) {
        }
        return null;
    }
/**
     * 将图片保存至文件
     *
     * @param filePath 文件路径
     * @param b    bitmap图片对象
     * @param quality   图片画质
     */
     public static void writeBitmapToFile(String filePath, Bitmap b, int quality) {
        try {
            File desFile = new File(filePath);
            FileOutputStream fos = new FileOutputStream(desFile);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            b.compress(Bitmap.CompressFormat.JPEG, quality, bos);
            bos.flush();
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
/**
     * 图片压缩
     *
     * @param image 压缩的图片对象
     * @return 返回bitmap对象
     */
private static Bitmap compressImage(Bitmap image) {
        if (image == null) {
            return null;
        }
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
            byte[] bytes = baos.toByteArray();
            ByteArrayInputStream isBm = new ByteArrayInputStream(bytes);
            Bitmap bitmap = BitmapFactory.decodeStream(isBm);
            return bitmap;
        } catch (OutOfMemoryError e) {
        } finally {
            try {
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
            }
        }
        return null;
    }
/**
     * 图片旋转角度
     *
     * @param b 旋转的图片对象
     * @param rotateDegree 旋转角度
     * @return 返回bitmap对象
     */
private static Bitmap rotateBitmap(Bitmap b, float rotateDegree) {
        if (b == null) {
            return null;
        }
        Matrix matrix = new Matrix();
        matrix.postRotate(rotateDegree);
        Bitmap rotaBitmap = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
        return rotaBitmap;
    }

三级图片缓存机制
  在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价—流量。对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理,每次打开应用都去网络获取图片,用户可就不乐意了,所以我们得用三级缓存策略(缓存层分为三层:内存层,磁盘层,网络层),如果内存或者本地磁盘中已有所需图片,就不用通过网络层获取图片,减少流量的损耗。
 关于缓存层的工作,当我们第一次打开应用获取图片时,先到网络去下载图片,然后依次存入内存缓存,磁盘缓存,当我们再一次需要用到刚才下载的这张图片时,就不需要再重复的到网络上去下载,直接可以从内存缓存和磁盘缓存中找,由于内存缓存速度较快,我们优先到内存缓存中寻找该图片,如果找到则运用,如果没有找到(内存缓存大小有限),那么我们再到磁盘缓存中去找。只要我们合理的去协调这三层缓存运用,便可以提升应用性能和用户体验。
1、内存层:(手机内存)
 内存缓存相对于磁盘缓存而言,速度要来的快很多,但缺点容量较小且会被系统回收,这里的实现我用到了LruCache。
LruCache这个类是Android3.1版本中提供的,如果你是在更早的Android版本中开发,则需要导入android-support-v4的jar包。
2、磁盘层:(SD卡)
 相比内存缓存而言速度要来得慢很多,但容量很大,这里的实现我用到了DiskLruCache类。
DiskLruCache是非Google官方编写,但获得官方认证的硬盘缓存类,该类没有限定在Android内,所以理论上java应用也可以使用DiskLreCache来缓存。
 这是DiskLruCache类的下载地址:http://pan.baidu.com/s/1o6tPjz8
3、网络层:(移动网络,无线网络)
 这个就没什么解释的了,就是我们上网用的流量。网络访问实现可以用开源框架Volley。
 开源框架Volley是2013年Google I/O大会发布的,Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮。它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。
 这是Volley的下载地址:http://pan.baidu.com/s/1kThedX9

-数组和链表的区别

数组结构在通过索引进行查询数据时效率比较高,而对于数组插入和删除操作,则效率会比较低,在第一个位置进行插入数据,其余数据就需要依次向后移动,而第一个数据进行删除,则需要所有数据全部向前移。
  链表:为了保证数据插入和删除,不会影响其他数据的移动,保证线性开销,就引出了指针链接,链表是由一系列节点组成的,每个节点都会有一个链点,next链,next链会执行下一个node的引用,所以我们在插入或者删除的时候,需要链表next链的指向地址即可,每个节点不需要内存进行连续存储,这样会减小删除和插入的线性开销。链表结构主要分为两种链表,单向链表和双向链表 ,即单向链表只有一个next链,而双向链表会有next链和pre链。
 简单的区别如下:
①数组静态分配内存,链表动态分配内存;②数组在内存中连续,链表不连续;③数组元素在栈区,链表元素在堆区;④数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);⑤数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。
​  数组:
​ 优点:使用方便 ,查询效率比链表高,内存为一连续的区域 。 缺点:大小固定,不适合动态存储,不方便动态添加。
 链表:
​ 优点:可动态添加删除,大小可变。 缺点:只能通过顺次指针访问,查询效率低。

后言
 有什么不对的地方还望多多指教,也欢迎大家关注我(简书/GitHub
谢谢观看此文!

相关文章

网友评论

      本文标题:Android interview share2

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