网络相关的客户端程序:(这其实是最多的一种)
1.新浪微博
2.人人网客户端
3.网易新闻
4.故事会
流程:
1.我们需要了解服务器返回数据的接口(一个非常宽泛的概念)信息.
例如:一个网络地址 ,<xml> 定义了版本号 定义新版本的地址
2.解析接口返回的数据.
3.把数据显示到界面.
用户登陆的流程.
1.提供界面让用户可以登陆到服务器上,完成用户身份的认证
2.提供一种身份,会话维持的技术, 识别当前登陆用户的身份状态.
WEB中的。
session 会话的id来识别用户.
cookie 本地硬盘上文件
android oauth认证技术.识别当前的请求来自于哪一个用户。
优米客户端的需求文档
iphone下的文档.
如果我一个iphone应用 移植到android.
1.查看iphone是怎么获取数据的 http://xxx.xxx.xxx.xx/pingdaoxinxi.xml
2.解析xml文件
3.显示到界面上.
关于从服务器上下载数据的操作有很多种:
1.解析xml
2.json
3.html 解析html的标签
02-29 01:39:42.147: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.MAIN cmp=com.android.settings/.WirelessSettings }
selector选择器
<merge xmlns:android="http://schemas.android.com/apk/res/android">
merge 合并 合体操作
<include layout="@layout/titlebar"/>
通过include的标签把定义的merge标签的内容引入到layout界面
开放平台:
网站 暴露出来一个webservice.
游戏大厅, 提供了一些接口.
web游戏 qq偷菜
广义讲 windows操作系统 也是一个开放平台.
核心的api暴露 windows api
android os
豆瓣网站 社交开放式平台
新浪微博
人人网
豆瓣API是豆瓣为第三方开发人员提供的编程接口。
利用豆瓣API,你可以在你的网站或程序中使用豆瓣的数据和功能
什么是服务器的接口 什么是服务器提供的api?
http://api.douban.com/book/subject/1220562 webservice
客户端通过接口访问服务器的数据 json xml html
实际上的操作
1.url
2.url 获取到一个urlconntection;
3.获取到服务器返回回来的具体数据信息
4.解析我们关心的内容
5.显示界面
使用开放平台的api 第一步
需要申请一个api使用key文件
为了保护豆瓣用户的数据;防止API被滥用或恶意使用,豆瓣要求每个API的使用者申请一个API Key, 而每个API Key唯一标识一个API使用者.
黑客, 抓取人人网数据的操作.
服务器根据api 的key 可以把你的客户端的请求给禁用.
你的豆瓣 API key:
0c51c1ba21ad8cfd24f5452e6508a6f7
API key 的详细信息 · · · · · ·
私钥:359e16e5e5c62b6e -请保护好你的私钥
应用名称:黑马小瓣瓣
创建时间: 2012-02-29
应用说明:
这个应用帮助用户快速访问豆瓣的数据,发豆瓣消息,写日记.
commons-codec-1.3.jar 公用的工具类
commons-httpclient-3.1.jar httpclient http请求
commons-logging-1.1.jar 日志的输出
c3p0 jdbc
douban-java-0.2.2-r34.jar 获取服务器数据 xml 格式 解析xml格式数据
gdata-client-1.0.jar
gdata-core-1.0.jar google提供的解析xml的工具
oauth-1.3.jar 用户身份认证的jar包
oauth认证的操作
通过qq号登陆京东网
http://fanli.qq.com/fanli_connect/qq_login.php?mall_id=360buy&mall_cb=http%3A%2F%2Fwww.360buy.com&url=http%3A%2F%2Fqq.360buy.com%2Fnew%2Fqq%2Fcallback.aspx&ts=20120229115122&flag=&forcelogin=1&vkey=87db3016f3f98dc6ac5b4168dfe17148
这个页面的服务器是在那一个公司?
顶级域名 qq.com
二级域名 fanli.qq.com
http://www.ccb.yinhang.com
.org
.com.cn
.us
http://www.ccb.yinhang.com
www.ccb.hah6.com
xxc.ccb.com
icbc.com
//得到了豆瓣后门的钥匙
83e32a78f6148aa28ba97f6ae23d9fe6
ab31cb1271593021
83e32a78f6148aa28ba97f6ae23d9fe6
ab31cb1271593021
特点:一旦我们用户第一次授权完毕后.
如果用户不取消授权 ,accesstoken 和 tokensecret不会发生改变
9644556d2ba3cabdc2cd004782eb6037
c78f514836b98fed
302 重定向.
jericho-html-3.1.jar html的解析包
对html进行面向对象的封装.
剖析ResourceType下的所有东西。
layer-list显然是一个图层的列表,作用就是一层一层的按照顺序叠加图片。
参看:http://blog.csdn.net/chenlaic/article/details/6089989
1.可以将多个图片按照顺序层叠起来
2.在drawable下建立一个xml文件
<?xml version="1.0" encoding="UTF-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<!--图片1-->
<item android:id="@+id/user_faceback_drawable"
android:drawable="@drawable/faceback" />
<!--图片2-->
<item android:id="@+id/user_face_drawable"
android:drawable="@drawable/h001"
android:left="10.0dip"
android:top="18.0dip"
android:right="25.0dip"
android:bottom="35.0dip" />
</layer-list>
<!--2个图片的叠加-->
每个item里面是一个图片,不过这个图片可以是png,jpg,gif也可以是我们用XML定义的图片。
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 是否支持渐变色 -->
<item>
<shape>
<gradient
android:startColor="#ffa6a6a6"
android:centerColor="#ffdbdbdb"
android:endColor="#ffe7e7e7"
android:height="1px"
android:angle="90"
android:dither="true" />
</shape>
</item>
</layer-list>
这个图层里面只有一张图片,其实也可以不这样做,可以直接用一个shape.
我们看到这张图片是一个shape,图片里面表示渐变色,它就是一个长高均为一的正方形,
这个正方形有渐变色,然后作为了一个背景图片,不过在作为背景的时间,引用它的
那个控件是填充父窗体的的,所以它会变成一个充满屏幕的矩形,那么渐变的色彩也会明显很多 。
调用: android:background="@drawable/home_gradient"
<!-- 因为它是src,所以它只是ImageView内的一部分,所以也会有android:paddingLeft这样的padding属性,如果是android:background它直接就填充整个 ImageView
根本没有padding这样的属性而言。-->
<ImageView
android:id="@+id/logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dip"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:scaleType="centerInside"
android:src="@drawable/logo" >
</ImageView>
有一个绝招,当你的系统想要进入系统的某个设置界面,但是又不知道
相应的activity,那么你可这样做,点击进入它,然后看打印出来的信息。
自定义对话框:(所有的布局呢都是自己写的,直接用的是Dialog)
<!-- 这个东西是从源码中获得的 ,我们主动去覆盖了默认的背景,并让其无标题-->
<style name="MyDialog" parent="@android:style/Theme.Dialog">
<item name="android:windowBackground">@drawable/title_background</item>
<item name="android:windowNoTitle">true</item>
</style>
dialog = new Dialog(this,R.style.MyDialog);
//使用这种方式,不可以得到这个View对象 ,不能获得里面的值,所以还是要吹起来。
//dialog.setContentView(R.layout.first_entry_dialog);
//这将是最简单的一种方法,至此把XML转换成View对象已有三种方法
View view = View.inflate(this, R.layout.first_entry_dialog, null);
edp1 = (EditText) view.findViewById(R.id.et_first_entry_pwd);
edp2 = (EditText) view.findViewById(R.id.et_first_entry_pwd_confirm);
Button ok = (Button) view.findViewById(R.id.bt_first_dialog_ok);
Button cancel = (Button) view.findViewById(R.id.bt_first_dialog_cancle);
ok.setOnClickListener(this);
cancel.setOnClickListener(this);
dialog.setContentView(view);
dialog.show();
//延时两秒进入new Handler().postDelayed(r, delayMillis) //通过handler 延时2秒 执行r任务
new Handler().postDelayed(new LoadMainTabTask(), 2000);
/**
* 得到网络状态
*/
public boolean isNetWorkConnected(){
ConnectivityManager manager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
//判断是wifi连接 还是 无线连接
// WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
// wifiManager.isWifiEnabled();
// wifiManager.getWifiState();
return (info!=null&&info.isConnected());//操,这个比三元表达式更牛逼。
// return (info!=null&&info.isConnected())?true:false;
}
最常用的tabhost.
其实它默认是在上面的。你想要让它在哪,要自己再定位。
tabhost这种东西默认的很难看,一般都自定义的。
selector是定义的一上东西在不同状态下的背景。
FitXY.
include merg两个标签 。
如果listview你不指定cacheColorHint="#0000000"
你点击的时间会显示出默认的颜色,所以把它改成透明的。
还有一个listSelector,当你选中的某个条目的时间要显示的颜色,
这次终于明白了。这两个listview下参数的含义。
还有一个divider这个表示每个条目之间的填充物。
tabhost:明白哪个是TabWidget哪个是tabcontent
一个重要的问题,有多个页面用到了同一个东西,跟JSP中一样,可以include过来。
让它作为一个单独的东西。
<merge xmlns:android="http://schemas.android.com/apk/res/android" >它表示
它是要被合并的。
在用的地方: <include layout="@layout/titlebar" />
<include layout="@layout/titlebar" />
<!--
include 包含某个布局
android:cacheColorHint 取消listview的背景
android:divider listview 里面两个item之间的背景
android:listSelector="@drawable/category_selector":点击 或者不点击这个条目(即这个条目在不同状态下的背景色)
-->
author:就是因为不信任才产生的,你不信任360,
你可以用QQ登陆,然后腾讯的服务器返回一个结果,
然后360用这个作为你登陆的凭证。
它每次请求都要
4a73c256be235a29df5b47043a6a0e7b
9dcf2bfa571799e2
登陆界面在最外层做一个ScrollView,这样做屏幕适配就非常的好。
找个那个解析HMTLjar包的API。
progressbar通常是在线程里面start,在handler里面dismiss;.
此属性意思是此视图是否显示,例如RelativeLayout中android:visibility="gone"
其有三个属性:visible显示;invisible显示黑背景条;gone不显示(不占空间)
在类中,可以设置其显示与否,setVisibility(View.GONE);不显示
setVisibility(View.VISIBLE);显示
xml中是visible
代码中是visibility
我发现了做WEB就是看HTTP协议和服务器返回的源码,然后我们对源码进行解析和封装。
既然你发现很多是一样的,所以要抽取出来。
之前我们在线程启动之前开个progressbar,子线程结束后,
发个消息告诉主线程,把那个progressbar关了,然后结束。
异步从网络下载操作,下载完毕自动放到页面中。太厉害了。非常常见的操作。
要做初始化和扫尾工作,但是它并不知道要怎么做,让调用者来做。
所以弄一个实现了该接口的对象给传进来。
其实就是调用者为了用这两个方法,我们必须把它给抽象出来,然后
通过构造函数把这个接口的实现给传递过来,那么调用 者就可以调用
接口里面的方法了。
异步加载过来,其实就是先把整个页面给展现出来,然后图片在自己在
后台下载,后台下载完毕后自动显示出来,绝大部分都是这样做的。
这是一个可以共用的图片异步下载方法。
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
/**
*
* 第一个参数 就是图片下载路径的url
* 第二个参数是 下载的进度
* 第三个参数就是异步任务执行完毕后的返回值
* @author Administrator
*
*/
public class LoadImageAsynTask extends AsyncTask<String, Void, Bitmap> {
LoadImageAsynTaskCallback loadImageAsynTaskCallback;
public LoadImageAsynTask(LoadImageAsynTaskCallback loadImageAsynTaskCallback) {
this.loadImageAsynTaskCallback = loadImageAsynTaskCallback;
}
public interface LoadImageAsynTaskCallback{
public void beforeLoadImage();
public void afterLoadImage(Bitmap bitmap);
}
/**
* 当异步任务执行之前调用
*/
@Override
protected void onPreExecute() {
//初始化的操作具体怎么去实现, LoadImageAsynTask 不知道
// 需要让调用这个 LoadImageAsynTask 的人 去实现
loadImageAsynTaskCallback.beforeLoadImage();
super.onPreExecute();
}
/**
* 异步任务执行之后调用
*/
@Override
protected void onPostExecute(Bitmap result) {
loadImageAsynTaskCallback.afterLoadImage(result);
super.onPostExecute(result);
}
/**
* 后台子线程运行的异步任务
* String... params 可变长度的参数
*/
@Override
protected Bitmap doInBackground(String... params) {
try {
String path = params[0];
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream is = conn.getInputStream();
return BitmapFactory.decodeStream(is);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
这也是一个经典的异步,第一个先把页面加载过来,加载完成之后,再去加载图片。是不是很牛逼。
@Override
public void fillData() {
new AsyncTask<Void, Void, Void>(){
//onPreExecute 在异步任务执行之前调用的方法
// 运行在主线程里面的
// 初始化ui的操作
@Override
protected void onPreExecute() {
showLoading();
super.onPreExecute();
};
// onPostExecute 在异步任务(后台任务)执行之后调用的方法
// 运行在ui线程中 ,
@Override
protected void onPostExecute(Void result) {
hideLoading();
super.onPostExecute(result);
tv_info.setText(content);
tv_location.setText(location);
tv_name.setText(name);
//设置用户的头像 ,这个是自定义实现的,其实那些系统的对话框这些东西也是这样实现的。
LoadImageAsynTask loadImageAsynTask = new LoadImageAsynTask(new LoadImageAsynTaskCallback() {
@Override
public void beforeLoadImage() {
iv_icon.setImageResource(R.drawable.ic_launcher);
}
@Override
public void afterLoadImage(Bitmap bitmap) {
if (bitmap!=null) {
iv_icon.setImageBitmap(bitmap);
}else{
iv_icon.setImageResource(R.drawable.ic_launcher);
}
}
});
loadImageAsynTask.execute(iconurl);
};
// doInBackground 后台执行的任务
// 方法运行在一个子线程当中
@Override
protected Void doInBackground(Void... params) {
// 执行耗时的操作
try {
UserEntry ue = doubanService.getAuthorizedUser();
name = ue.getTitle().getPlainText();
location = ue.getLocation();
content = ((TextContent) ue.getContent()).getContent().getPlainText();
for (Link link : ue.getLinks()) {
if ("icon".equals(link.getRel())) {
System.out.println("图片 。"+link.getHref());
iconurl = link.getHref();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
那些 listview中,不可能每次读取一次就从网络下载一次 ,肯定是要缓存起来。如果在缓存中就用缓存中的,
如果不在,就重新下载。
通过构造方法和成员变量配合的传值是一种传值的非常重要的手段。
1、异步加载图片,非常重要。
2、加载过的图片存在SD卡上,直接用缓存,十分重要。
3、可以不用2,用更好的方法,软引用,不会增加用户的SD卡负担。
为了不每次从互联网上下载图片,而是从缓存中读取,有几种方法。
1、存到SD卡上。
2、在java里面还有一种引用类型,叫做软引用,它是在java虚拟机的层面保证
java虚拟机会尽量长时间的保留引用的对象。
当java虚拟机发现内存不足的时侯,才去回收软件软引用的对象。
我们可以使用软件引用的对象做内存缓存。
软件引用对象其实是一个容器,包装类。
key:是图片的URL
value:是一个软引用类型的bitmap
//软引用
Map<String, SoftReference<Bitmap>> iconCache;
//初始化内存缓存
iconCache = new HashMap<String, SoftReference<Bitmap>>();
//第二种方法:把图片存储到内存缓存里面,把bitmap的软件引用存储到map集合里面。
iconCache.put(iconname, new SoftReference<Bitmap>(bitmap));
如果listview数据量很大10万条。
1、分页加载,每个页面显示的条目都一样多。
2、分批加载。
当滚动到最下方,并且静止的时间再加载五条,所以
就是加一个滚动的监听事件。
如果有人问,10000条数据怎么办?
1、分批,分页加载。
2、如果每个条目中有大对象,异步加载,然后把大对象存储到软件引用中。
3、如果引用的内存溢出,写一个类继承application.
软引用当内存不足的时间先给清空,如果把所有的软引用清空后,
还显示内存不足的时间,才会爆出内存不足的错误。
待做?
public class MyApp extends Application{
/**
* 当内存不足的时间调用这个方法。
*/
@Override
public void onLowMemory() {
super.onLowMemory();
// 发送一些广播 关闭掉一些activity service
Intent intent = new Intent();
intent.setAction("kill_activity_action");
sendBroadcast(intent);
}
}
然后在相应的activity里面写广播接收者的类,并为其注册,在相应的方法里面处理。
这个方法是onScrollStateChanged拖住滑动。
/**
* 在代码中注册的广播接收者话,你要在destory方法里面把广播接收者
* 反注册掉。否则会报错。
*/
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
虽然分批加载可以在一定程序上解决大数据量问题,不过
加载过多还是会产生内存溢出问题。
分页获取数据?
分页原理:指定每一个页面显示的最大数目,每个页面最多
显示内容为100条。
book movie music等。
为什么这种分页不是很好呢?因为我们API没有提供这种方法
第二,当这个listview中某个条目为空的时间可以用
setEmptyView()去填充,例如用某个图片等。
上下文菜单:
先在主UI里面注册
registerForContextMenu(subjectlist);
/**
* 创建菜单
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
/**
* 监听菜单
*/
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
int position = (int) info.id;
Note note = (Note) subjectlist.getItemAtPosition(position);
NoteEntry entry = note.getNoteEntry();
switch (item.getItemId()) {
case R.id.menu_add_note:
return true;
case R.id.menu_delete_note://删除也是一个耗时的操作。
deleteNote(entry);
return true;
case R.id.menu_edit_note:
return true;
}
return super.onContextItemSelected(item);
}
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_add_note"
android:title="添加日记">
</item>
<item
android:id="@+id/menu_edit_note"
android:title="修改日记">
</item>
<item
android:id="@+id/menu_delete_note"
android:title="删除日记">
</item>
</menu>
1. AsyncTask的三个泛型参数说明(三个参数可以是任何类型)
2. 第一个参数:传入doInBackground()方法的参数类型
3. 第二个参数:传入onProgressUpdate()方法的参数类型
4. 第三个参数:传入onPostExecute()方法的参数类型,也是doInBackground()方法返回的类型。
execute的参数类型是这个任务要接受的参数,也就是doInBackground执行的参数,这个类型与第一个类型
是一致的,如果这个任务的执行不需要参数,可以为空。
private void deleteNote(NoteEntry entry) {
new AsyncTask<NoteEntry, Void, Boolean>() {
@Override
protected void onPostExecute(Boolean result) {
pd.dismiss();
if (result) {
fillData();
}else {
showToast("删除日记失败");
}
super.onPostExecute(result);
}
@Override
protected void onPreExecute() {
pd = new ProgressDialog(MyNoteActivity.this);
pd.setTitle("正在删除日记");
pd.show();
super.onPreExecute();
}
@Override
protected Boolean doInBackground(NoteEntry... params) {
try {
doubanService.deleteNote(params[0]);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}.execute(entry);
}
新增成功之后 ,finish当前的activity,返回到列表页面的时间,自动让这条日记新增出来
,很明显,在那个页面要setResult(200);然后在列表页面重写onActivityResult方法,让它重新
获取数据即可。
编辑日记是一个非常好的操作。
第一,它用到了不同的请求码去对应同一个页面。
第二,更新时间如何把日记给传过去 。有两种方法,一种是
放在Bundle中,另外一种是放在全局的app中。
case R.id.menu_edit_note:
Intent editIntent = new Intent(MyNoteActivity.this,NewNoteActivity.class);
editIntent.putExtra("iseditnote", true);//用来区别是更新还是新增。
//把数据放到全局里面,那边好取。
MyApp myApp = (MyApp) getApplication();
myApp.note = note;
//需要告诉NewNoteActivity操作这是一个编辑日记的操作。
startActivityForResult(editIntent, EDIT_NOTE);
return true;
取:
boolean flag = getIntent().getBooleanExtra("iseditnote", false);
if (false) {
// 编辑日记 从全局中取数据
MyApp myApp = (MyApp) getApplication();
Note note = myApp.note;
EditTextTitle.setText(note.getTitle());
EditTextContent.setText(note.getContent());
.........
}else {
// 新日记
}
我的错误,写完Application后,一定要在配置文件里面注册,否则会爆出类型转换异常。
程序中的异常处理?十分重要,在面试中可以大说,特说的东西。
打开之后突然不见了,就是这些捕获的异常。UncaughtExceptionHandler
这个是十分重要的,如果出现异常,程序会自动退出,并且把错误的所有信息
发送到服务器上,让工程师去解决。
Build这个类里面有你手机的固件信息。
通过解析HTML数据获取我们需要的内容。
一淘网,抓取各种购物网站的同种商品。这是在别人没有开放网络接口的时间
获取别人的数据,它是从HTML里面直接获取的。
用jericho-html-3.1jar包。
这个东西是自己先分析别人的HTML,然后用J2SE项目调试。
看一它相关的资料和文档。
http://jericho.htmlparser.net/docs/javadoc/index.html
/**
* Html解析 获取新书数据
* @param context
* @return
* @throws Exception
*/
public static List<NewBook> getNewBooks(Context context ) throws Exception{
String path =context.getResources().getString(R.string.newbookpath);
URL url = new URL(path);
URLConnection conn = url.openConnection();
Source source = new Source(conn);
List<NewBook> newbooks = new ArrayList<NewBook>();
List<Element> lielements = source.getAllElements("li");
System.out.println(lielements.size());
for(Element lielement : lielements){
List<Element> childrenlists = lielement.getChildElements();
if(childrenlists.size()==2){
if("detail-frame".equals(childrenlists.get(0).getAttributeValue("class"))){
NewBook newbook = new NewBook();
//数目对应的div信息
Element div = childrenlists.get(0);
List<Element> divChildren = div.getChildElements();
String name = divChildren.get(0).getTextExtractor().toString();
newbook.setName(name);
String description = divChildren.get(1).getTextExtractor().toString();
newbook.setDescription(description);
String summary = divChildren.get(2).getTextExtractor().toString();
newbook.setSummary(summary);
Element achild = childrenlists.get(1);
String iconpath = achild.getChildElements().get(0).getAttributeValue("src");
newbook.setIconpath(iconpath);
newbooks.add(newbook);
}
}
}
return newbooks;
}
十分重要的问题,出现图片乱跳的现象?
虽然使用listview的缓存,很简单,效率高,不过
由于它缓存了历史的view对象,不过,当你的图片
是异步下载的时间会出现跳图片的现象,因为缓存了
图片,会出现新的条目一直显示老的图片,并且一直在
与新的图片切换。
其实浪费时间的操作都在View.inflate这个方法的操作上。
我们在布局里面把imageview干掉,在代码里面生成
我们自己定义的imageview就不会再被listview缓存。
PreferenceActivity可以直接用它。
配置信息的页面这样用。其实在系统的设置里面其实都是用的这个activity.
参看项目中的代码 。只要记住Setting里面基本用的都是PreferenceActivity。
在线格式化JSON格式 。
每一个大括号是一个JSON对象----JSONObject
每一个中括号叫一个JSON数组----JSONArray.
{}JSON对象里面的内容,必须是键值对的形式,如果不是就是产生JSONException.
<!-- 自定义activity为弹出窗float window -->
<style name="floatwindow" parent="@android:style/Theme.Dialog">
<item name="android:windowBackground">@drawable/background</item>
</style>
导入代码问题:
douban笔记
最新推荐文章于 2019-12-23 22:31:29 发布