android面试集锦总结二

android部分:
这里的android根据面试官的水平,面试官水平高的话,会问很多源码级的东西,并且问的非常细,这个就没办法了,不过相对来说还是占少数的,当然高大上的公司就必须做好心理准备了。现在来说一般比较常问的android技术点

首先从四大组件说起:
Activity:
生命周期:
activity三种状态:运行(运行在最前端)、停止(不可见,完全被覆盖)、暂停(可见,但前端还有其他activity)
生命周期相关的方法:onCreate-onStart-onResume-onPause-onStop-onDestory-onRestart
切换时如果要保存数据, 可以重写: onSaveInstanceState();
恢复数据时, 重写: onRestoreInstanceState();
启动模式:
1.standard:默认的,每次调用startActivity()启动时都会创建一个新的activity放在栈顶
2.singleTop:启动Activity时,指定Activity不在任务栈栈顶就创建,如在栈顶,则不会创建,会调用onNewInstance(),复用已经存在的实例。
3.singleTask:在任务栈里面只允许一个实例,如果启动activity不存在就创建,如果存在直接跳转到指定Activity所在位置。
4.singleInstance:开启一个新的任务栈来存放这个Activity的实例,此模式开启的Activity是运行在自己单独的任务栈中的。

2.BroadcastReceiver广播接收者
有序广播用过调用abortBroadcast()方法来中断,接收者之间可以传递数据
动态注册广播register,取消unregister
广播接收者打开Activity,需要设置一下Intent.FLAG_ACTIVITY_NEW_TASK
应为广播接收者是没有Activity任务栈的
sendOrderBroadcast()发送有序广播
1)静态注册:在AndroidManifest.xml注册,android不能自动销毁广播接收器,也就是说当应用程序关闭后,还是会接收广播。
2)动态注册:在代码中通过registerReceiver()手工注册.当程序关闭时,该接收器也会随之销毁。当然,也可手工调用unregisterReceiver()进行销毁。

3.Service服务
Service中的生命周期方法(Context调用执行):
1)startService() 如果没创建就先onCreate()再startCommand(), 如果已创建就只执行startCommand();
2)stopService() 执行onDestroy()
3)bindService() 如果没有创建就先onCreate()再onBind()
4)unbindService() 如果服务是在绑定时启动的, 先执行onUnbind()再执行onDestroy(). 如果服务在绑定前已启动, 那么只执行onUnbind();
3、开启服务的2种方式
2种不同开启方式的区别:
1)startService:
开启服务,服务一旦开启,就长期就后台运行,即使调用者退出来,服务还会长期运行;
资源不足时,被杀死,资源足够时,又会复活;
2)bindService:
绑定服务,绑定服务的生命周期会跟调用者关联起来,调用者退出,服务也会跟着销毁;
通过绑定服务,可以间接的调用服务里面的方法(onBind返回IBinder);
4、服务混合调用生命周期
一般的调用顺序:
①、start -> stop 开启 –> 结束
②、bind -> unbind 绑定(服务开启) -> 解绑(服务结束)
混合调用:
①、start –> bind -> stop->unbind->ondestroy 通常不会使用这种模式
开启 –> 绑定 –> 结束(服务停不了)->解除绑定(服务才可停掉)
②、start –> bind -> unbind -> stop 经常使用
开启 –> 绑定 –> 解绑(服务继续运行)-> stop(不用时,再停止服务)
这样保证了服务长期后台运行,又可以调用服务中的方法

4、内容提供者
这个问的非常少,但是一旦问道还是要知道怎么回事的。
ContentProvider:
在数据库中有对应的增删改查的方法,如果要让别的应用程序访问,需要有一个路径uri
通过content:路径对外暴露,uri写法:content://主机名/表名
1)ContentProvider:内容提供者
把一个应用程序的私有数据(如数据库)信息暴露给别的应用程序,让别的应用程序可以访问;
在数据库中有对应的增删改查的方法,如果要让别的应用程序访问,需要有一个路径uri:
通过content:// 路径对外暴露,uri写法:content://主机名/表名
2)ContentResolver:内容解析者
根据内容提供者的路径,对数据进行操作(crud);
3)ContentObserver:内容观察者
可以理解成android系统包装好的回调,数据发送变化时,会执行回调中的方法;
ContentResolver发送通知,ContentObserver监听通知;
当A的数据发生变化的时候,A就会显示的通知一个内容观察者,不指定观察者,就会发消息给一个路径
ContentProvider和sql的实现上的区别:
1,Contentprovider屏蔽了数据存储的细节,内部实现对用户完全透明,用户只需要i、关心操作数据的uri就可以了,ContentProvider可以实现不同app之间的共享
2,Sql也有增删改查的方法,但是sql只能查询本应用下的数据库。而Comtentprovider还可以去增删改查本地文件.xml文件的读取等

异步加载网络数据(AsyncTask)
AsyncTask类,这个类中的任务是运行在后台线程中的,并可以将结果放在UI线程中去处理
它定义了三种泛型,分别是Params、Progress和Result,分别表示请求的参数、任务的进度和获取的结果数据
执行过程:1.onPreExecte():执行在主线程。这步操作是用于准备好任务的,作为任务加载的准备工作。建议在这个方法中弹出一个提示框。
2.doInBackground():执行在子线程中。需要将请求的参数传递进来,发送给服务器,并将获取到的数据返回,数据回传给下一步的onProgressUpdate()中进行进度更新。
3.onProgressUpdate():进度更新
4.onPostExectue():界面更新
实现原理:
1.线程池的创建:默认创建一个线程池ThreadPoolExecutor,并默认创建出5个线程放入到线程池中,最多可放128个线程,且这个线程池是公共的唯一一份。
2.任务的执行:执行run方法,执行完run方法后,会调用scheduleNext()不断的从双端队列中轮询,获取下一个任务并继续放到一个子线程中执行,直到异步任务执行完毕。
3.消息的处理:在AsyncTask中维护了一个InternalHandler的类,这个类是继承Handler的,获取的数据是通过handler进行处理和发送的。其中handleMessage方法中,将消息传递给onProgressUpdate()进行进度的更新,也可以将结果发送到主线程中,进行界面的更新了。

LisView优化:
ListView如何提高其效率
1.复用ContentView
2.自定义静态类viewholder
3.使用分页加载
4.使用weakReference引用ImageView对象
listView可以显示多种类型的条目:
Listview显示的每个条目都是通过baseAdapter的getView来展示的,理论上我们完全可以让每个条目都是不同类型的view,除此之外adapter还提供了getViewTypeCount()和getItemViewType(int position)两个方法。在getview方法中我们可以根据不同的viewtype加载不同的布局文件。

ListView中的数据分批及分页加载:
设置ListView的滚动监听器:setOnScrollListener
1.在监听器中有两个方法:滚动状态发生变化的方法onScrollStateChanged和listView被滚动时调用的方法
2.在滚动状态发生改变的方法有三个状态:触摸滑动、惯性滚动、静止状态
3.对不同的状态进行处理:分批加载数据,只关心静止状态:如果最后一个可见条目就是数据适

配器里的最后一个,此时可加载更多的数据。

ListView图片优化
1.不要直接拿路径去循环decodeFile();使用Option保存图片大小,不要加载图片到内存
2.拿到图片一定要经过边界压缩
3.在listView去图片是也不要直接拿个路径去取图片,而是以WeakReference代替强引用
4.在getView中做图片转换时,产生的中间变量一定及时释放
异步加载图片基本思想:
1.先从内存缓存中获取图片显示(内存缓冲)
2.获取不到的话从SD卡里获取(SD卡缓存)
3.都获取不到的话从网络下载图片并保存到SD卡同时加入内存并显示
图片错位问题:
本质是因为listView使用了缓存convertView。可见则显示,不可见则不显示。在imageLoader里有个imageViews的map对象,用于保存当前显示区域图像对应的url集,在显示前判断处理一下即可。
内存缓冲机制:
首先限制内存图片缓冲的堆内存大小,每次有图片往缓存里加时判断是否超过限制大小,超过的话取最少使用的图片并将其移除
二级缓存:从LinkedHashMap里移除的缓存放在SoftReference里
LinkedHashMap缓存在没有移除出去之前是不会被GC回收的,而SoftRefernce里的图片缓存在没有其他引用保存时随时都会被GC回收。
ListView的其他优化:
1.尽量避免在BaseAdapter中使用static来定义全局静态变量
2.尽量使用getApplicationContext
3.尽量避免在ListView适配器中使用线程

ScrollView和ListView的冲突问题:
在ScrollView添加ListView会导致listView控件显示不全,两个控件的滚动事件冲突导致。通过listView中的item数量去计算listView的显示高度。

熟悉XML/Json解析数据,以及数据存储方式
数据存储方式包括:File、SharedPreference、XML/Json、数据库、网络
XML/Json解析数据

Handler机制和事件分发机制
Message:消息,由MessageQueue统一列队,终由Handler处理
Handler:处理者,负责Message发送消息及处理。Handler通过与Looper进行沟通,从而使用Handler时,需要实现handlerMessage方法来对特定的Message进行处理
MessageQuene:消息队列,用来存放Handler发送过来的消息,按照先入先出规则执行。
Looper:消息泵,不断从MessageQueue中取出Message执行。因此,一个线程中的MessaeQueue需要一个Looper进行管理。
耗时操作,比如网络请求、文件处理、多媒体处理需要在子线程中操作,手机显示的刷新频率60Hz,一秒钟刷新60次,没16.7毫秒刷新一次,为了不丢帧,主线程处理代码最好不要超过16毫秒。
Handler消息机制
在主线程中 Android 默认已经调用了 Looper.preper()方法,调用该方法的目的是在 Looper 中创建MessageQueue 成员变量并把 Looper 对象绑定到当前线程中。当调用 Handler 的 sendMessage(对象)方法的时
候就将 Message 对象添加到了 Looper 创建的 MessageQueue 队列中,同时给 Message 指定了 target 对象,其实这个 target 对象就是 Handler 对象。主线程默认执行了 Looper.looper()方法,该方法从 Looper 的成员变量MessageQueue 中取出 Message,然后调用 Message 的 target 对象的 handleMessage()方法。这样就完成了整个消息机制。

事件分发机制
onTouch和onTouchEvent
这两个方法都是在View的dispathTouchEvent中调用的,onTouch优先于onTouchEvent执行,在onTouch中返回true将事件消费掉,onTouchEvent将不会再执行。
依次下发,下发的过程是调用View的dispatchTouchEvent方法实现的。简单来说,就是viewgroup遍历包含者的子view,调用每个View的dispatchTouchEvent方法,而当子view为viewgroup时,又会调用viewgroup的dispatchTouchEvent方法继续调用内部的view的dispatchTouchEvent方法。
touch事件分发有两个主角:viewGroup和view。
viewgroup包含onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent
view包含dispatchTouchEvent、onTouchEvent两个
onInterceptTouchEvent有两个作用:1.拦截down事件的分发 2.中止Up和move事件向目标view传递,使得目标view所在的viewgroup捕获up和move事件
触摸事件是有action_Down、Action_Move、Action_Up组成,其中一次完整的触
摸事件中,Down和Up都只有一个,Move有若干个,可以为0个。

自定义控件
1.自定义组合控件
声明一个view对象,继承相对布局,或者线性布局或者其他的viewGroup
在自定义的view对象里面重写它的构造方法,在构造方法里面把布局初始化
根据业务需要添加一些api方法,扩展自定义组合控件
在布局文件里面可以自定义一些属性
声明自定义属性的命名空间
在res目录下的values目录下创建attrs.xml的文件声明我们写的属性
在布局文件中写自定义的属性
使用自定义的属性
2.view的绘制过程
mesarue()过程:为整个view树计算实际的大小
view : mMeasuredHeight高和mMeasureWidth()宽
viewGroup:重写onMeasure()方法,遍历measure()过程,通过调用父类ViewGroup类里面的measureChildWithMargins()方法去实现
layout()根据子视图的大小以及布局参数将view树放到合适的位置上
view: 设置该view视图位于父视图的坐标抽即mLeft,mTop,mLeft,mBottom,回调onLayout方法
viewGroup:遍历每个子视图childView,调用该子视图的layout()方法去设置它的坐标值
3.draw()绘制过程
viewRoot对象的performTraversals()方法调用draw()方法发起绘制view树不需要全部重绘只需要绘制需要绘制的部分

这个控件中,父视图使用unspecified dimensions来将它的每个子视图都测量一次来算出它们到底需要多大尺寸,而这些子视图没被限制的尺寸的和太大或太小,所以会用精确数值再次调用measure()(也就是说,如果子视图不满意它们获得的区域大小,那么父视图将会干涉并设置第二次测量规则)。其中measure()方法会调用onMeasure()方法。
代码中,由于把每行剩余空间重新分配,会调用了requestLayout()方法,这个方法又会导致measure()和onLayout()方法的再次调用。
最后你会发现 onMeasure()方法调用了 1次*2*2=4次 onLayout()方法调用了 1次*2 =2次

谈一谈android的安全机制
1,在安卓是有文件权限的控制,在清单文件声明
2,每个android中每个应用都有自己的/data/data/包名 文件夹,该文件夹只能该应用访问,而其他应用则无权访问
3,Android的代码混淆保护了开发者的劳动成果

多线程断点续传下载
多线程下载的实现过程:
1,首先得到下载文件的长度,然后设置本地文件的长度。
HttpURLConnection.getContentLength();
RandomAccessFile file = new RandomAccessFile(“FeiQ.exe”,”rwd”);
file.setLength(filesize); //设置本地文件的长度
2,根据文件长度和线程数计算每条线程下载的数据长度和下载位置。
如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如图所示。
3,使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止.
如:指定从文件的2M位置开始下载,下载到位置4M为止,代码如下:
HttpURLConnection.setRequestProperty(“Range”, “bytes=2097152-4194303”);
4,保存文件
使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。
RandomAccessFile threadfile = new RandomAccessFile(“QQWubiSetup.exe “,”rwd”);
threadfile.seek(2097152); //从文件的什么位置开始写入数据

数据库操作
在Android系统,提供了一个SQLiteOpenHelper抽象类,该类用于对数据库版本进行管理.该类中常用的方法:
onCreate 数据库创建时执行(第一次连接获取数据库对象时执行)
onUpgrade 数据库更新时执行(版本号改变时执行)
onOpen 数据库每次打开时执行(每次打开数据库时调用,在 onCreate,onUpgrade方法之后)
Android提供了一个名为SQLiteDatabase的类,该类封装了一些操作数据库的API,使用该类可以完成对数据进行添加(Create)、查询(Retrieve)、更新(Update)和删除(Delete)操作(这些操作简称为CRUD)。对SQLiteDatabase的学习,我们应该重点掌握execSQL()和rawQuery()方法。 execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句; rawQuery()方法用于执行select语句。

aidl:接口声明语言,跨进程通信
bindService有一个ServiceConnec接口覆写onServiceConnect方法,把第二个参数IBinder对象强制转换为aidl中的接口类

- 写服务类

    1. 定义一个接口文件, 声明一个方法forwardPayMoney方法, 把后缀名修改为.aidl, 并且把修饰词去掉. 

    2. 在服务中定义一个内部类MyBinder, 继承Stub类, 并且把抽象方法forwardPayMoney实现了.

    3. 在onBind方法中把第二部定义的内部类对象MyBinder返回.

- 另一个程序的Activity

    4. 使用隐式的方式绑定服务, 传递过去一个连接桥对象.

    5. 把服务程序中的aidl文件拷贝当前工程中, 包名要保留一致.

    6. 在连接桥对象中的onServiceConnected方法中, 把IBinder对象转换成aidl接口对象

            mAlipayRemoteService = Stub.asInterface(service);

    7. 使用aidl接口对象, 调用接口中的抽象方法, 实际上会调用到远程服务中内部类中的forwardPayMoney方法.

android中的动画
1.View Animation: 视图动画/ Frame动画/属性动画:这种动画是可扩展的,

图片处理框架
imageLoader:imageLoaderEngine,cache及
imageDownloader,imageDecoder,bitmaodisplayer,bitmapProcessor五大模块
简单来说就是imageLoader收到加载及显示图片的任务,并将它交给
imageLoaderEngine,ImageLoaderEngine分发任务到具体线程池去执行,任务通过cache及imageDownloder获取图片。
优点:1,支持下载监听2,可以在view滚动中暂停图片加载3.默认实现多种内存缓存算法4.支持本地缓存文件名规则定义
picasso
这个库分为dispatcher/requestHandler及Downloader,picassoDrawable等模块
picasso收到加载及显示图片的任务,创建Request并将他交给
Dispatcher,dispatcher分发任务到具体的requesthandler,任务memoryCache及Handler获取图片,图片获取成功后通过picassoDrawable显示到Target中
优点:1.自带统计监控功能2.支持优先级处理3.支持延迟加载4.支持飞行模式、并发线程数根据网络类型而变

图片缓存处理:
LruCache类:主要算法原理是把最近使用的对象用强引用存储在在LinkedHashMap中,并且把最近最少使用的对象在缓存值达到预定值之前从内存中移除。

内存溢出原因:
1.资源释放问题
2.对象内存过大
3.static
4.线程导致内存溢出

图片占用进程的内存算法简介
android中处理图片的基础类是Bitmap,顾名思义,就是位图。占用内存的算法如下:
图片的width*height*Config。
如果Config设置为ARGB_8888,那么上面的Config就是4。一张480*320的图片占用的内存就是480*320*4 byte。
在默认情况下android进程的内存占用量为16M,因为Bitmap除了java中持有数据外,底层C++的 skia图形库还会持有一个SKBitmap对象,因此一般图片占用内存推荐大小应该不超过8M。这个可以调整,编译源代码时可以设置参数。

Activity的启动与生命周期的监控
应用程序被开启后,是需要开启并创建Activity,加载相应的view,从而展示出应用程序
1、Activity是通过startActivity开启起来的,startActivity是由有Context调用的,其具体的实现类是ContextImpl
在ContextImpl中的startActivity方法中,会调用ActivityThread的相关方法【mMainThread.getInstrumentation().execStartActivity()】;可以追溯到Instrumentation这个类,其中的execStartActivity()的方法中实现了startActivity的调用:ActivityManagerNative.getDefault().startActivity,由此可以看出是底层进行处理。
2、ActivityMonitor监控Activity
当Activity实例创建的时候,就会给Activity配置一个监视器ActivityMonitor,监控Activity的声明周期:
在Instrumentation的execStartActivity()的方法中,上来先判断ActivityMonitor是否为null:在第一次开启Activity的时候,ActivityMonitor还是null的,就会调用ActivityManagerNative.getDefault().startActivity(…..),是在操作native底层的信息,从而执行startActivity,再去开启一个Activity。
简单来说,就是通过调用JNI,调用startActivity方法,开启Activity;创建好了之后,随即也创建好了Activity的监视器ActivityMonitor
3、在ActivityMonitor中就有Activity各种生命周期的监控
①、在newActivity方法中:
可以通过拿到Activity的字节码,创建一个Activity,并将这个Activity返回
还会调用attach方法,传入ActivityThread的线程
②、在各种生命周期的方法中,调用activity的各自的生命周期的方法

总结:
1、通过PackageManagerService将所有用到的资源加载进内存中
2、在Launcher中,将view等控件加载到ViewGroup中,点击每个item会有相应的操作
3、在公开的文档中是找不到具体调用startActivity的类的,而是由系统完成调用的,实现了Activity的启动
实际就是通过Context的实现类ContextImpl进行调用的,一步步转到底层(ActivityManagerNative)实现调用
4、另一个重要的类就是ActivityMonitor,监控Activity生命周期的;在其newActivity方法中创建了Activity,并调用了attach方法;
也就是说当一个Activity被创建的时候,就会绑定一个ActivityMonitor,用来监控Activity的生命周期

沉浸式状态栏实现思路
首先看下第一种方式
系统的方式沉浸式状态栏实现
步奏一
//当系统版本为4.4或者4.4以上时可以使用沉浸式状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//透明导航栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
步奏二
布局加入: android:fitsSystemWindows=”true” android:clipToPadding=”true”
我们看下activity和布局文件
FirstActivity.java:
/**
* 沉浸式状态栏
*/
private void initState() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//透明导航栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}

activity_first.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:fitsSystemWindows="true"
        android:clipToPadding="true"
        android:layout_width="match_parent"
        android:layout_height="140dp"
        android:textSize="24dp"
        android:background="@color/mask_tags_1"
        android:text="你好,沉浸式状态栏"/>
</LinearLayout>

实现思路,添加隐藏布局,然后我们动态的计算状态栏的高度,然后把这个高度设置成这个隐藏的布局的高度,便可以实现
在这里我们通过反射来获取状态栏的高度

/**
     * 通过反射的方式获取状态栏高度
     *
     * @return
     */
    private int getStatusBarHeight() {
        try {
            Class<?> c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = Integer.parseInt(field.get(obj).toString());
            return getResources().getDimensionPixelSize(x);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

ViewFilpper类和ViewPager的区别
1.ViewFilpper类继承于ViewAnimator类。而ViewAnimator类继承于FrameLayout。
查看ViewAnimator类的源码可以看出此类的作用主要是为其中的View切换提供动画效果。该类有如下几个和动画相关的方法。
2.ViewPager用于实现多页面的切换效果,该类存在于Google的兼容包里面,所以在引用时记得在BuilldPath中加入“Android-support-v4.jar”

单例模式:

饿汉式:
public class Singleton {
// 直接创建对象
public static Singleton instance = new Singleton();
// 私有化构造函数
private Singleton() {
}
// 返回对象实例
public static Singleton getInstance() {
return instance;
}
}
懒汉式:
public class Singleton {
// 声明变量
private static volatile Singleton singleton = null;
// 私有构造函数
private Singleton() {
}
// 提供对外方法
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}

SQLite可以解析大部分标准SQL语句,如:
查询语句:select * from 表名 where 条件子句 group by 分组字句 having … order by 排序子句

如:select * from person
select * from person order by id desc
select name from person group by name having count(*)>1

分页SQL与MySQL类似,下面SQL语句获取5条记录,跳过前面3条记录

select * from Account limit 5 offset 3 或者 select * from Account limit 3,5

插入语句:insert into 表名(字段列表) values(值列表)。如: insert into person(name, age) values(‘工工’,3)
更新语句:update 表名 set 字段名=值 where 条件子句。如:update person set name=‘工‘ where id=10
删除语句:delete from 表名 where 条件子句。如:delete from person where id=10

支付
导入jar
将demo里面的alipaySdk-20160223.jar拷贝到我们工程的libs下,并添加到依赖中
配置
权限





activity

String orderInfo = getOrderInfo("测试的商品", "该测试商品的详细描述", "0.01");
/**
 * 特别注意,这里的签名逻辑需要放在服务端,切勿将私钥泄露在代码中!
 */
String sign = sign(orderInfo);try {
    /**
     * 仅需对sign 做URL编码
     */
    sign = URLEncoder.encode(sign, "UTF-8");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}
/**
 * 完整的符合支付宝参数规范的订单信息
 */final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();

Runnable payRunnable = new Runnable() {

    @Override
    public void run() {
        // 构造PayTask 对象
        PayTask alipay = new PayTask(MainActivity.this);
        // 调用支付接口,获取支付结果
        String result = alipay.pay(payInfo, true);

        Message msg = new Message();
        msg.what = SDK_PAY_FLAG;
        msg.obj = result;
        mHandler.sendMessage(msg);
    }
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();

处理支付结果

@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {
    @SuppressWarnings("unused")
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case SDK_PAY_FLAG: {
                PayResult payResult = new PayResult((String) msg.obj);
                /**
                 * 同步返回的结果必须放置到服务端进行验证(验证的规则请看https://doc.open.alipay.com/doc2/
                 * detail.htm?spm=0.0.0.0.xdvAU6&treeId=59&articleId=103665&
                 * docType=1) 建议商户依赖异步通知
                 */
                String resultInfo = payResult.getResult();// 同步返回需要验证的信息

                String resultStatus = payResult.getResultStatus();
                // 判断resultStatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档
                if (TextUtils.equals(resultStatus, "9000")) {
                    Toast.makeText(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                } else {
                    // 判断resultStatus 为非"9000"则代表可能支付失败
                    // "8000"代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)
                    if (TextUtils.equals(resultStatus, "8000")) {
                        Toast.makeText(MainActivity.this, "支付结果确认中", Toast.LENGTH_SHORT).show();

                    } else {
                        // 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误
                        Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show();

                    }
                }
                break;
            }
            default:
                break;
        }
    }

};

这里支付成功了,只是提示用户,还得从服务器确认是否正在支付了,我这里只写了本地,其他如果在服务端实现是一样的,你把这代码直接发给后端就行了(如果后端是Java开发),可以看到我们已经成功调起支付宝服务了

JSON解析
android的json解析部分都在包org.json下,主要有以下几个类:
JSONObject:可以看作是一个json对象,这是系统中有关JSON定义的基本单元,其包含一对儿(Key/Value)数值。它对外部(External: 应用toString()方法输出的数值)调用的响应体现为一个标准的字符串(例如:{“JSON”: “Hello, World”},最外被大括号包裹,其中的Key和Value被冒号”:”分隔)。其对于内部(Internal)行为的操作格式略微,例如:初始化一个JSONObject实例,引用内部的put()方法添加数值:new JSONObject().put(“JSON”, “Hello, World!”),在Key和Value之间是以逗号”,”分隔。Value的类型包括:Boolean、JSONArray、JSONObject、Number、String或者默认值JSONObject.NULL object 。
JSONStringer:json文本构建类 ,根据官方的解释,这个类可以帮助快速和便捷的创建JSON text。其最大的优点在于可以减少由于 格式的错误导致程序异常,引用这个类可以自动严格按照JSON语法规则(syntax rules)创建JSON text。每个JSONStringer实体只能对应创建一个JSON text。。其最大的优点在于可以减少由于格式的错误导致程序异常,引用这个类可以自动严格按照JSON语法规则(syntax rules)创建JSON text。每个JSONStringer实体只能对应创建一个JSON text。
JSONArray:它代表一组有序的数值。将其转换为String输出(toString)所表现的形式是用方括号包裹,数值以逗号”,”分隔(例如: [value1,value2,value3],大家可以亲自利用简短的代码更加直观的了解其格式)。这个类的内部同样具有查询行为, get()和opt()两种方法都可以通过index索引返回指定的数值,put()方法用来添加或者替换数值。同样这个类的value类型可以包括:Boolean、JSONArray、JSONObject、Number、String或者默认值JSONObject.NULL object。
JSONTokener:json解析类
JSONException:json中用到的异常

android中里的HTML网页里点击某一按钮或某一位置直接跳转某一Activty里去
废话不多说,这次教程的目标如下
1.android 中的java代码调用webview里面的js脚本
2.webview中的js脚本调用本地的java代码
3.java调用js并传递参数
4.js调用java并传递参数
2、创建Activty,在Activty的onCreate里实现三个步骤:
· //第一步:webview支持script脚本
· WebSettings webSetting = mWebHtml.getSettings();
· webSetting.setJavaScriptEnabled(true);
· //第二步:定义交互类与方法
· final class ServiceJavaScriptInterface {
· ServiceJavaScriptInterface() {
· }
· public void startGridViewHttp() {
· //跳转到界面
· startActivity(new Intent(WebHtml.this, Gridmview.class));
· }
}
· //第三步:添加script接口
mWebHtml.addJavascriptInterface(
new ServiceJavaScriptInterface(),”musicServiceInterfaceName”);
}
3、在head里写一个取名yun(任意取)的方法名:
function yun(){
window.musicServiceInterfaceName.startGridViewHttp();
}
4.这时必须在HTML里设置点击监听:

<img src="./img/index_yaoqinghan.png" onclick="yun()"/> 

Eventbus
。EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。
2、基本使用
(1)自定义一个类,可以是空类,比如:
(2)在要接收消息的页面注册:
(3)发送消息
(4)接受消息的页面实现(共有四个函数,各功能不同,这是其中之一,可以选择性的实现,这里先实现一个):
1、onEvent
2、onEventMainThread
3、onEventBackgroundThread
4、onEventAsync
(5)解除注册

Rxjava
RxJava 的异步实现,是通过一种扩展的观察者模式来实现的。
RxJava 的观察者模式
它就是一个实现异步操作的库
RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。Observable 和Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。
与传统观察者模式不同, RxJava 的事件回调方法除了普通事件 onNext() (相当于 onClick() / onEvent())之外,还定义了两个特殊的事件:onCompleted() 和 onError()。
onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的onNext() 发出时,需要触发 onCompleted() 方法作为标志。
onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
2. 基本实现
基于以上的概念, RxJava 的基本实现主要有三点:
1) 创建 Observer
Observer 即观察者,它决定事件触发的时候将有怎样的行为
2) 创建 Observable
Observable 即被观察者,它决定什么时候触发事件以及触发怎样的事件
3) Subscribe (订阅)
创建了 Observable 和 Observer 之后,再用 subscribe() 方法将它们联结起来,整条链子就可以工作了。

MVC模式
View:对应于布局文件
Model:业务逻辑和实体模型
Controllor:对应于Activity
MVP模式
View 对应于Activity,负责View的绘制以及与用户交互
Model 依然是业务逻辑和实体模型
Presenter 负责完成View于Model间的交互

RecyclerView可以通过导入support-v7对其进行使用。
据官方的介绍,该控件用于在有限的窗口中展示大量数据集
通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator
你想要控制其显示的方式,请通过布局管理器LayoutManager
你想要控制Item间的间隔(可绘制),请通过ItemDecoration
你想要控制Item增删的动画,请通过ItemAnimator
你想要控制点击、长按事件,请自己写(擦,这点尼玛。)
系统没有提供ClickListener和LongClickListener。
实现的方式比较多,你可以通过mRecyclerView.addOnItemTouchListener去监听然后去判断手势,
当然你也可以通过adapter中自己去提供回调

还有很多技术点,再有时间补充,暂时就这些。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值