2017年4月7日,周结(七),解析json数据(IPHelper拿来练手)以及其他的知识点

来源:互联网 发布:松下a4调试软件 编辑:程序博客网 时间:2024/04/28 03:32

这周总的来说收获还是蛮大的,学到了好多知识,尤其是网络请求方面,学会了解析服务器返回的 json 数据.


json 数据转换为实体类对象,并取出相应数据(使用 OKhttp 和 Gson )


代码如下:


添加依赖库

compile'com.squareup.okhttp3:okhttp:3.6.0'
compile'com.google.code.gson:gson:2.7'



数据请求接口是知乎的每日新闻

http://news-at.zhihu.com/api/4/news/latest


代码展示

public classMainActivityextendsAppCompatActivity {
privateButtonbutton;
privateTextViewdate_text;
privateTextViewstories_text;
privateProgressBarprogressBar;
privateGsongson;
privateGsonBuilderbuilder;
privateStringurl="http://news-at.zhihu.com/api/4/news/latest";
StringBufferstringBuffer=newStringBuffer();

@Override
protected voidonCreate(finalBundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button= (Button) findViewById(R.id.button);
progressBar= (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(View.INVISIBLE);
date_text= (TextView) findViewById(R.id.date_text);
stories_text= (TextView) findViewById(R.id.stories_text);
button.setOnClickListener(newView.OnClickListener() {
@Override
public voidonClick(View v) {
showProgressBar();
sendHttpWithOkHttp();
}
});
Thread thread = Thread.currentThread();
Log.d("","");
}

public voidsendHttpWithOkHttp() {
OkHttpClient client =newOkHttpClient();
finalRequest request = newRequest.Builder().url(url).build();
client.newCall(request).enqueue(newCallback() {
@Override
public voidonFailure(Call call, IOException e) {
runOnUiThread(newRunnable() {
@Override
public voidrun() {
Toast.makeText(MainActivity.this,"请求失败", Toast.LENGTH_SHORT).show();
}
});
}

@Override
public voidonResponse(Call call, finalResponse response) throwsIOException {
finalString content = response.body().string();

runOnUiThread(newRunnable() {
@Override
public voidrun() {
Toast.makeText(MainActivity.this,"请求成功", Toast.LENGTH_SHORT).show();
builder=newGsonBuilder();
gson=builder.create();
ZhiHu zhiHu =gson.fromJson(content, ZhiHu.class);
List<ZhiHu.StoriesBean> beanList = zhiHu.getStories();
for(ZhiHu.StoriesBean storiesBean : beanList) {
stringBuffer.append(storiesBean.getTitle() + "---");
}
date_text.setText(zhiHu.getDate());
stories_text.setText(stringBuffer);
closeProgressBar();
}
});
}
});
}

/**
* 设置加载进度条是否显示
*/
public voidshowProgressBar() {
if(progressBar==null) {
progressBar.setVisibility(View.VISIBLE);
}
}

public voidcloseProgressBar() {
if(progressBar!=null) {
progressBar.setVisibility(View.INVISIBLE);
}
}
}

结果展示


解析数据如果使用框架的话其实很简单,只不过原来自己一直把它复杂化了,使用 OKhttp 发送网络请求获取到的数据在 UI 中回显时,需要 runOnUiThread 中 更新才行而 retrofit 无需这样,因为 retrofit 封装了OKhttp




使用 butterknife 时有个 bug:
If this view is optional add '@Nullable' (fields) or '@Optional' (methods)annotation.
找不到资源的id
百度一下结果是 butterknife 本身的 bug


解决方法:自己手动重新 findviewById...




退出时的弹窗提示,代码如下:

/*
back键退出程序时弹窗提示
*/
@Override
public booleanonKeyDown(intkeyCode, KeyEvent event) {
switch(keyCode) {
caseKeyEvent.KEYCODE_BACK:
AlertDialog.Builder builder =newAlertDialog.Builder(this);
builder.setIcon(R.drawable.exit)
.setTitle("提示")
.setMessage("确认退出程序?")
.setPositiveButton("确定",newDialogInterface.OnClickListener() {
@Override
public voidonClick(DialogInterface dialog,intwhich) {
finish();
}
})
.setNegativeButton("取消",newDialogInterface.OnClickListener() {
@Override
public voidonClick(DialogInterface dialog,intwhich) {

}
})
.show();
break;
}
return false;
}


IPHelper
无需登录注册什么的打开之后就一个页面

一个输入框,一个 button 按钮
输入框最好是自己自定义的样式

点击 button 之后会跳转到另一个页面,显示出ip的详细信息

会用到的框架
retrofit 用于发送网络请求
gson 用来解析服务器返回的json数据
litepal 用来管理数据库
Phoenix 用来下拉刷新(只是为了好看...)

数据库把最近查询过的 ip 都存储起来
输入框搞一个自动匹配

button 背景被拉伸的问题:简单的办法就是设置为固定宽高

使用自动匹配输入框时不要忘了设置android:completionThreshold这个属性




Toast 使用的小技巧:

publicclassUtil {
privatestatic Toast toast;
publicstaticvoid showToast(Context context, String content) {
if (toast == null) {
toast = Toast.makeText(context, content, Toast.LENGTH_SHORT); 
}else {
toast.setText(content);
}
toast.show();
}

这里和我们平时使用 Toast 的方式并不一样,这里会先判断 Toast 对象是否为空,如果是空的情况下才会调用 makeText() 方法来去生成一个 Toast 对象,否则就直接调用 setText() 方法来设置显示的内容,最后再调用 show() 方法将 Toast 显示出来。




想试着让手机震动,类似 qq 的特别关心发来消息一样

添加震动权限:
<uses-permissionandroid:name="android.permission.VIBRATE"/>

Activity中的添加如下代码:
privateVibratorvibrator;
vibrator= (Vibrator) getAppliation().getSystemService(VIBRATOR_SERVICE);
long[] pattern = {100,300,100,300};// 停止 开启 停止 开启
vibrator.vibrate(pattern,-1);//重复两次上面的pattern 如果只想震动一次,index设为-1




动态申请权限:
以 call_phone 为例
先添加一个 button
<Button
android:id="@+id/call_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:text="点击打电话"/>
Activity 中的代码如下
public class MainActivity extendsAppCompatActivity {
privateButtoncall_btn;

@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
call_btn= (Button) findViewById(R.id.call_btn);
call_btn.setOnClickListener(newView.OnClickListener() {
@Override
public voidonClick(View v) {
if(ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,newString[]{Manifest.permission.CALL_PHONE},1);
}else{
Call();
}
}
});
}

public voidCall() {

Intent intent =newIntent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10010"));
startActivity(intent);
}

@Override
public voidonRequestPermissionsResult(intrequestCode, String[] permissions,int[] grantResults) {
switch(requestCode) {
case1:
if(grantResults.length>0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Call();
}else{
Toast.makeText(this,"你拒绝了权限", Toast.LENGTH_LONG).show();
}
break;
default:
}
}
}
点击拨打电话按钮后首先判断一下用户是否授予可拨打电话的权限,通过方法ActivityCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CALL_PHONE) 第一个参数为 context ,第二个参数为具体的权限名,然后通过方法的返回值和 PackageManager.PERMISSION_GRANTED做比较,相等就说明用户已经授权,不等就表示用户没有授权.已经授权的话,直接拨打电话即可.
未授权的话需要调用 ActivityCompat.requestPermissions(MainActivity.this,newString[]{Manifest.permission.CALL_PHONE},1)来向用户申请授权,第一个参数为Activity实例,第二个参数为具体权限名组成的数组,第三个是请求码,只要是唯一值即可.调用该方法之后会弹出一个权限申请的对话框,最终会回调到 onRequestPermissionsResult(intrequestCode, String[] permissions,int[] grantResults)方法中,授权的结果会封装进 grantResults 中,判断一下授权结果,如果同意的话就调用call方法,拒绝的话会 Toast 一句话.




读取手机短信

/**
* 获取短信内容和发件人并且存储到数据库中的msg表中
*/
public voidgetMsgFromPhone() {

Cursor cursor = getContentResolver().query(Uri.parse("content://sms"),null,null,null,null);
if(cursor !=null) {
while(cursor.moveToNext()) {
String msg_content = cursor.getString(cursor.getColumnIndex("body"));
String msg_receive_people = cursor.getString(cursor.getColumnIndex("address"));
//不知道为什么永远是空
//String msg_send_people = cursor.getString(cursor.getColumnIndex("person"));
String msg_type = cursor.getString(cursor.getColumnIndex("type"));
// Log.e("获取到的短信内容:", msg_content);
if(msg_type.equals("1")) {
// Log.e("获取到的发件人", msg_receive_people);
msg ms =newmsg(msg_content, msg_receive_people);
ms.save();
}else if(msg_type.equals("2")) {
// Log.e("获取到的发件人", myNum);
msg ms =newmsg(msg_content, myNum);
ms.save();
}
}
}
Toast_show.showToast(getApplicationContext(),"获取完成");
cursor.close();
}
不要忘了申请权限~

获取手机短信需要调用该方法 getContentResolver().query(Uri.parse("content://sms"),null,null,null,null) 来得到一个 cursor 类型的变量,该变量中的一行数据即为一条短信对象,通过 cursor.moveToNext() 方法判断是否有未读取的数据, String msg_receive_people = cursor.getString(cursor.getColumnIndex("address")) 该行代码可以得到一条短信的收件人/发件人, String msg_content = cursor.getString(cursor.getColumnIndex("body")) 获取到短信的内容.



以上这么多就是这周主要学习到的知识.



0 0
原创粉丝点击