五一后,被ji金伤了,哇呜呜,还是得苦逼老老实实打工写代码,看下面吧

本篇实现效果:

实现登录用户名展示到用户中心页面上,并且页面有个人信息,订单列表,修改密码,意见反馈发送到服务端,前面登录后,通过SharedPreferencestoken值保存到本地,退出登录时,用editor.clear()直接清除保存的koten,跳转到登录界面。本篇用的技术同样是gson+okhttp,老生常谈了,写过那么多遍,因该都懂了,哈哈~,我就当这样默认了。


文章导航

一、【Android项目实战 | 从零开始写app(一)】 创建项目

二、【Android项目实战 | 从零开始写app(二)】实现闪屏页,启动app

三、【Android项目实战 | 从零开始写app(三)】实现引导页,进入登录or主页面

四、【Android项目实战 | 从零开始写app(四)】Okhttp+Gson实现服务端登录验证功能

五、【Android项目实战 | 从零开始写app(五)】okhttp+gson实现服务端注册功能

六、【Android项目实战 | 从零开始写app(六)】用TabLayout+ViewPager搭建App 框架主页面底部导航栏

七、【Android项目实战 | 从零开始写app(七)】优化主页导航栏,禁用主页页面滑动切换效果

八、【Android项目实战 | 从零开始写app(八)】实现app首页广告轮播图切换和搜索跳转

九、【Android项目实战 | 从零开始写app(九)】Tablayout+ViewPager实现页面分类顶部标题页面联动切换

十、【Android项目实战 | 从零开始写app(十)】Okhttp+glide+json+ListView实现新闻模块数据的填充显示

十一、【Android项目实战 | 从零开始写app(十一)】实现app首页智慧服务页面服务分类数据的解析及点击跳转

十二、【Android项目实战 | 从零开始写app(十二)】实现app首页智慧服务&热门推荐&热门主题、新闻

十三、【Android项目实战 | 从零开始写app(十三)】实现用户中心模块清除token退出登录&信息修改等功能

十四、【Android项目实战 | 从零开始写app(十四)】实现图片发布模块 | 必知必会之调用系统相机拍照、相册

十五、【Android项目实战 | 从零开始写app(教程汇总)】Android 项目实战系列汇总、源代码


功能逻辑实现

在前面的基础上,继续完善项目,没有的请看前面系列文章

UserFragment:

在UserFragment中加入下面代码:

package com.example.myapp.fragment;import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TextView;import androidx.appcompat.widget.Toolbar;
import androidx.viewpager.widget.ViewPager;import com.example.myapp4.R;
import com.example.myapp4.activity.AdviseActivity;
import com.example.myapp4.activity.LoginActivity;
import com.example.myapp4.activity.OrderActivity;
import com.example.myapp4.activity.UpdataPSWActivity;
import com.example.myapp4.activity.UserInfoActivity;/*** @ProjectName: MyApp* @Package: com.example.myapp.fragment* @ClassName: UserFragment* @Description:* @Author: liyingxia* @CreateDate: 2021/05/06 22:50*/
public class UserFragment extends BaseFragment implements View.OnClickListener {private static final String TAG = UserFragment.class.getSimpleName();private TextView tv_usercenter;private TextView tv_username;private ImageButton user_img;private Button btn_out;private Intent intent = null;private LinearLayout ll_info;private LinearLayout ll_order;private LinearLayout ll_update;private LinearLayout ll_advice;private Toolbar toolbar;@Overridepublic View initView() {Log.i(TAG, "用户中心的视图被实例化了");View view = View.inflate(getContext(), R.layout.fragment_user, null);ll_advice = view.findViewById(R.id.ll_advice);ll_info = view.findViewById(R.id.ll_info);ll_order = view.findViewById(R.id.ll_order);ll_update = view.findViewById(R.id.ll_update);btn_out = view.findViewById(R.id.btn_out);tv_username = view.findViewById(R.id.tv_username);user_img = view.findViewById(R.id.user_img);ll_update.setOnClickListener(this);ll_info.setOnClickListener(this);ll_order.setOnClickListener(this);ll_advice.setOnClickListener(this);btn_out.setOnClickListener(this);user_img.setOnClickListener(this);return view;}
/*    @Overridepublic void onStart() {super.onStart();toolbar.setTitle("个人中心");//setSupportActionBar(toolbar);toolbar.setNavigationIcon(R.mipmap.top_bar_left_back);toolbar.setNavigationOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {// finish();}});}*/@Overridepublic void initData() {super.initData();// 读取本地保存用户的登录信息SharedPreferences sp = getActivity().getSharedPreferences("token_data", Context.MODE_PRIVATE);String user = sp.getString("username","");// 把用户名显示到textView控件上tv_username.setText(user);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.ll_info:intent = new Intent(getContext(), UserInfoActivity.class);break;case R.id.ll_order:intent = new Intent(getContext(), OrderActivity.class);break;case R.id.ll_update:intent = new Intent(getContext(), UpdataPSWActivity.class);break;case R.id.ll_advice:intent = new Intent(getContext(), AdviseActivity.class);break;case R.id.btn_out:SharedPreferences.Editor editor = getActivity().getSharedPreferences("token_data", Context.MODE_PRIVATE).edit();editor.clear(); // 清除本地保存的token值editor.apply();intent = new Intent(getContext(), LoginActivity.class);break;case R.id.user_img:break;}// 页面跳转startActivity(intent);}
}

上面的editor.clear() 实现清除本地保存的token值,最后记得apply()提交。其他都是简单点击实现页面跳转。

fragment_user.xml:

用户中心页面布局,一些文本text,color等资源应该放到style目录下,方便后期维护修改,比较统一,但我没有这样做,就直接这样写了,你们可以自己实现,不清楚的看我前面文章:Android 实现国际化效果

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/tv_usercenter"android:layout_width="match_parent"android:layout_height="45dp"android:background="#22349C"android:gravity="center"android:padding="10dp"android:text="个人中心"android:textColor="#fff"android:textSize="20sp" /><LinearLayoutandroid:layout_below="@id/tv_usercenter"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="170dp"android:background="#3F51B5"><ImageButtonandroid:id="@+id/user_img"android:layout_width="50dp"android:layout_height="50dp"android:layout_centerInParent="true"android:background="@mipmap/top_image_icon" /><TextViewandroid:id="@+id/tv_username"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_marginTop="130dp"android:text="我是李子哈"android:textColor="#ffffff" /></RelativeLayout><Viewandroid:layout_width="match_parent"android:layout_height="8dp"android:background="#eee" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:id="@+id/ll_info"android:orientation="horizontal"><TextViewstyle="@style/TextStyle"android:text="个人信息" /><ImageButtonandroid:id="@+id/ib_user_info"android:layout_width="40dp"android:layout_marginLeft="230dp"android:layout_height="40dp"android:background="@null"android:src="@mipmap/home_arrow_right"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginLeft="45dp"android:background="#eee" /><LinearLayoutandroid:id="@+id/ll_order"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:orientation="horizontal"><TextViewstyle="@style/TextStyle"android:text="订单列表" /><ImageButtonandroid:id="@+id/ib_order_list"android:layout_gravity="left"android:layout_width="40dp"android:layout_marginLeft="230dp"android:layout_height="40dp"android:background="@null"android:src="@mipmap/home_arrow_right"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginLeft="45dp"android:background="#eee" /><LinearLayoutandroid:id="@+id/ll_update"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:baselineAligned="false"android:orientation="horizontal"><TextViewstyle="@style/TextStyle"android:text="修改密码" /><ImageButtonandroid:layout_gravity="left"android:layout_width="40dp"android:id="@+id/ib_update_psw"android:layout_marginLeft="230dp"android:layout_height="40dp"android:background="@null"android:src="@mipmap/home_arrow_right"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginLeft="45dp"android:background="#eee" /><LinearLayoutandroid:id="@+id/ll_advice"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:baselineAligned="false"android:orientation="horizontal"><TextViewstyle="@style/TextStyle"android:text="意见反馈" /><ImageButtonandroid:layout_gravity="left"android:layout_width="40dp"android:id="@+id/ib_advise"android:layout_marginLeft="230dp"android:layout_height="40dp"android:background="@null"android:src="@mipmap/home_arrow_right"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginLeft="45dp"android:background="#eee" /><Buttonandroid:layout_margin="15dp"android:layout_width="match_parent"android:layout_height="40dp"android:text="退出账号"android:textStyle="bold"android:textColor="#ffffff"android:background="#A3184FF1"android:id="@+id/btn_out"/></LinearLayout></RelativeLayout>

AdviseActivity:

意见反馈页面

package com.example.myapp4.activity;import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.example.myapp.R;
import com.example.myapp.utils.APIConfig;
import com.example.myapp.utils.GetToken;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;public class AdviseActivity extends AppCompatActivity implements View.OnClickListener {private ImageButton btn_back;private EditText content;private Button btn_send;// 更新主线程的UI@SuppressLint("HandlerLeak")private Handler handler = new Handler(){// 接收消息@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);if (msg.what==1) {String re = msg.obj.toString();Toast.makeText(getApplicationContext(),"反馈成功:"+re,Toast.LENGTH_LONG).show();}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_advise);initView();}private void initView() {btn_back = (ImageButton) findViewById(R.id.btn_back);content = (EditText) findViewById(R.id.content);btn_send = (Button) findViewById(R.id.btn_send);btn_back.setOnClickListener(this);btn_send.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_back:finish();break;case R.id.btn_send:SendAdavice();break;}}// 发送建议反馈到服务端private void SendAdavice() {String contentString = content.getText().toString().trim();if (TextUtils.isEmpty(contentString)) {Toast.makeText(this, "内容不能为空", Toast.LENGTH_SHORT).show();return;}// 获取SharedPreferences对象SharedPreferences sp = this.getSharedPreferences("token_data",MODE_PRIVATE);String token = sp.getString("token","");// 实例化OkHttpClient 对象OkHttpClient client = new OkHttpClient();//  实例化 JSONObjectJSONObject object = new JSONObject();try {object.put("content",contentString);object.put("userid",8888);} catch (JSONException e) {e.printStackTrace();}// 设置传递的数据类型MediaType mediaType = MediaType.parse("application/json;charset=utf-8"); RequestBody requestBody = RequestBody.create(mediaType,object.toString());Request request = new Request.Builder().post(requestBody).url(APIConfig.BASE_URL+"/userinfo/feedback").addHeader("Authorization",token).build();Call call = client.newCall(request);call.enqueue(new Callback() {// 响应失败@Overridepublic void onFailure(Call call, IOException e) {Log.i("onFailure",e.getMessage());}// 响应成功@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response.isSuccessful()) {String result = response.body().string();// 创建Message 对象Message msg = new Message();/** what是自定义的一个Message的识别码,以便于在Handler的handleMessage方    *法中根据what识别出不同的Message,以便我们做出不同的处理操作*/msg.what=1;// 通过给obj赋值Object类型传递向Message传入请求到的数据msg.obj=result;// 发送消息handler.sendMessage(msg);}}});}
}

MediaType指的是要传递的数据的MIME类型,MediaType对象包含了三种信息:typesubtype以及charset,一般将这些信息传入parse()方法中,这样就可以解析出MediaType对象,比如 “application/json; charset=utf-8” ,用来告诉服务端消息主体是序列化后的 JSON 字符串 charset=utf-8 则表示采用UTF-8编码。如果不知道某种类型数据的MIME类型,可以参见Media Type和MIME 参考手册,这里不再多说。

  • json : application/json
  • xml : application/xml
  • png : image/png
  • jpg : image/jpeg
  • gif : imge/gif

这里用Handler 处理异步消息处理,它的主要作用:消息处理者,主要用于发送跟处理消息,发送消息:SendMessage(),处理消息: HandleMessage()
子线程中更新主线程的UI。

Handler是android线程之间的消息机制,主要的作用是将一个任务切换到指定的线程中去执行,(准确的说是切换到构成handler的looper所在的线程中去出处理)android系统中的一个例子就是主线程中的所有操作都是通过主线程中的handler去处理的。

上面的msg.what=1中的what是自定义的一个Message的识别码,以便于在Handler的handleMessage方法中根据what识别出不同的Message,以便我们做出不同的处理操作。通过给obj赋值Object类型传递向Message传入请求到的数据。

activity_advise.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:orientation="vertical"android:layout_height="match_parent"tools:context=".activity.AdviseActivity"><RelativeLayoutandroid:layout_margin="10dp"android:layout_width="wrap_content"android:layout_height="wrap_content"><ImageButtonandroid:id="@+id/btn_back"android:layout_width="40dp"android:layout_height="40dp"android:background="@null"android:layout_alignParentLeft="true"android:src="@mipmap/top_bar_left_back1"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="意见反馈"android:textStyle="bold"android:layout_toRightOf="@id/btn_back"android:textColor="#000000"android:textSize="20sp"android:gravity="center"/></RelativeLayout><LinearLayoutandroid:layout_margin="20dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:background="@drawable/login_form_bg"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="18sp"android:text="请输入您的意见:"/><EditTextandroid:layout_width="match_parent"android:layout_height="200dp"android:background="@null"android:id="@+id/content"android:hint=""/></LinearLayout><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="提交"android:id="@+id/btn_send"android:layout_margin="20dp"android:textColor="#fff"android:textSize="22sp"android:background="@drawable/login_btn_bg"/></LinearLayout>

修改密码:

UpdataPSWActivity:

package com.example.myapp4.activity;import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.myapp4.R;
import com.example.myapp4.bean.LoginBean;
import com.example.myapp4.bean.UserBean;
import com.example.myapp4.utils.APIConfig;
import com.google.gson.Gson;import org.json.JSONException;
import org.json.JSONObject;import java.io.IOException;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;public class UpdataPSWActivity extends AppCompatActivity implements View.OnClickListener {private ImageButton btn_back;private EditText userId;private EditText et_old_psw;private EditText et_new_psw;private Button btn_update;private Button btn_clear;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_updata_psw);initView();}private void initView() {btn_back = (ImageButton) findViewById(R.id.btn_back);userId = (EditText) findViewById(R.id.userId);et_old_psw = (EditText) findViewById(R.id.et_old_psw);et_new_psw = (EditText) findViewById(R.id.et_new_psw);btn_update = (Button) findViewById(R.id.btn_update);btn_clear = (Button) findViewById(R.id.btn_clear);btn_back.setOnClickListener(this);btn_update.setOnClickListener(this);btn_clear.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_back:finish();break;case R.id.btn_update:Update();break;case R.id.btn_clear:userId.setText("");et_old_psw.setText("");et_new_psw.setText("");break;}}private void Update() {String userIdString = userId.getText().toString().trim();if (TextUtils.isEmpty(userIdString)) {Toast.makeText(this, "请输入你的用户编号", Toast.LENGTH_SHORT).show();return;}String old_password = et_old_psw.getText().toString().trim();if (TextUtils.isEmpty(old_password)) {Toast.makeText(this, "请输入你的原始密码", Toast.LENGTH_SHORT).show();return;}String password = et_new_psw.getText().toString().trim();if (TextUtils.isEmpty(password)) {Toast.makeText(this, "请输入你的新密码", Toast.LENGTH_SHORT).show();return;}SharedPreferences sp = getSharedPreferences("token_data",MODE_PRIVATE);String user_psw = sp.getString("password","");String token = sp.getString("token","");OkHttpClient client = new OkHttpClient();JSONObject json = new JSONObject();try {json.put("userId",userIdString);json.put("oldPwd",old_password);json.put("password",password);} catch (JSONException e) {e.printStackTrace();}MediaType mediaType = MediaType.parse("application/json;charset=utf-8");RequestBody requestBody  = RequestBody.create(mediaType,json.toString());Request request = new Request.Builder().url(APIConfig.BASE_URL+"/system/user/resetPwd").addHeader("Authorization",token).post(requestBody).build();Call call = client.newCall(request);call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.i("请求失败",e.getMessage());}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response.isSuccessful()) {String result = response.body().string();Gson gson = new Gson();LoginBean loginBean = gson.fromJson(result,LoginBean.class);String code = loginBean.getCode();if (code=="200") {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(UpdataPSWActivity.this,"密码更新成功:"+result,Toast.LENGTH_LONG).show();}});}}}});}
}

activity_updata_psw.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#EFEDED"android:orientation="vertical"><RelativeLayoutandroid:layout_margin="10dp"android:layout_width="wrap_content"android:layout_height="wrap_content"><ImageButtonandroid:id="@+id/btn_back"android:layout_width="40dp"android:layout_height="40dp"android:background="@null"android:layout_alignParentLeft="true"android:src="@mipmap/top_bar_left_back1"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="修改密码"android:textStyle="bold"android:layout_centerHorizontal="true"android:layout_toRightOf="@id/btn_back"android:textColor="#000000"android:textSize="20sp"android:gravity="center"/></RelativeLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="#F6F5F4"/><LinearLayoutandroid:layout_marginRight="20dp"android:layout_marginLeft="20dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/login_form_bg"android:orientation="vertical"><LinearLayoutandroid:layout_marginTop="12dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="用户编号:"android:layout_marginTop="10dp"android:textSize="18sp"android:textColor="#000000"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/userId"android:textSize="16sp"android:background="@null"android:layout_margin="5dp"android:hint="请输入你的用户编号"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="15dp"android:background="#F6F5F4"/><LinearLayoutandroid:layout_marginTop="12dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="原始密码:"android:layout_marginTop="10dp"android:textSize="18sp"android:textColor="#000000"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/et_old_psw"android:textSize="16sp"android:background="@null"android:layout_margin="5dp"android:hint="请输入你的原始密码"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="15dp"android:background="#F6F5F4"/><LinearLayoutandroid:layout_marginTop="12dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingBottom="10dp"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="新密码:"android:layout_marginTop="10dp"android:textSize="18sp"android:textColor="#000000"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/et_new_psw"android:textSize="16sp"android:background="@null"android:layout_margin="5dp"android:hint="请输入你的新密码"/></LinearLayout></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="20dp"android:orientation="vertical"><Buttonandroid:id="@+id/btn_update"android:layout_marginTop="50dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="确定"android:textSize="20sp"android:textColor="#ffffff"android:background="@drawable/login_btn_bg"/><Buttonandroid:id="@+id/btn_clear"android:layout_marginTop="10dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="清空"android:textSize="18sp"android:textColor="#2196F3"android:background="@drawable/login_form_bg"/></LinearLayout></LinearLayout>

个人信息:

修改个人信息属于个人隐私的数据,在请求服务端数据时,需要在okhttp中的addHeader("Authorization",token)请求头带上Authorization 标识的token值来验证请求。

UserInfoActivity:

package com.example.myapp.activity;import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.myapp.R;
import com.example.myapp.bean.ResponseBean;
import com.example.myapp.utils.APIConfig;
import com.google.gson.Gson;
import org.json.JSONObject;
import java.io.IOException;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;public class UserInfoActivity extends AppCompatActivity implements View.OnClickListener {private ImageButton btn_back;private ImageView ib_img;private EditText et_nicke;private EditText et_phone;private EditText et_email;private EditText et_idetity;private RadioButton rb_man;private RadioButton rb_woman;private RadioGroup rg_sex;private Button btn_update;private Button btn_clear;private String sex = "";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_user_info);initView();}private void initView() {btn_back = (ImageButton) findViewById(R.id.btn_back);ib_img = (ImageView) findViewById(R.id.ib_img);et_nicke = (EditText) findViewById(R.id.et_nicke);et_phone = (EditText) findViewById(R.id.et_phone);et_email = (EditText) findViewById(R.id.et_email);et_idetity = (EditText) findViewById(R.id.et_idetity);rb_man = (RadioButton) findViewById(R.id.rb_man);rb_woman = (RadioButton) findViewById(R.id.rb_woman);rg_sex = (RadioGroup) findViewById(R.id.rg_sex);btn_update = (Button) findViewById(R.id.btn_update);btn_clear = (Button) findViewById(R.id.btn_clear);btn_back.setOnClickListener(this);btn_update.setOnClickListener(this);btn_clear.setOnClickListener(this);rg_sex.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup radioGroup, int i) {if (rb_man.isChecked()) {sex = "1";} else {sex = "0";}}});}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_back:finish();break;case R.id.btn_update:UpdateInfo();break;case R.id.btn_clear:// 清空et_nicke.setText("");et_phone.setText("");et_phone.setText("");et_idetity.setText("");et_email.setText("");sex = "";break;}}private void UpdateInfo() {//输入校验String nicke = et_nicke.getText().toString().trim();if (TextUtils.isEmpty(nicke)) {Toast.makeText(this, "请输入昵称", Toast.LENGTH_SHORT).show();return;}String phone = et_phone.getText().toString().trim();if (TextUtils.isEmpty(phone)) {Toast.makeText(this, "请输入你的手机号码", Toast.LENGTH_SHORT).show();return;}String email = et_email.getText().toString().trim();if (TextUtils.isEmpty(email)) {Toast.makeText(this, "请输入你的邮箱地址", Toast.LENGTH_SHORT).show();return;}String idetity = et_idetity.getText().toString().trim();if (TextUtils.isEmpty(idetity)) {Toast.makeText(this, "4405281999121411040640", Toast.LENGTH_SHORT).show();return;}if (TextUtils.isEmpty(sex)){Toast.makeText(this, "请选择你的性别", Toast.LENGTH_SHORT).show();return;}SharedPreferences sp = this.getSharedPreferences("token_data",MODE_PRIVATE);String token = sp.getString("token","");String username = sp.getString("username","");// 实例化 OkHttpClientOkHttpClient client = new OkHttpClient();// 实例化 JSONObjectJSONObject object = new JSONObject();try {object.put("userId",111);object.put("idCard",idetity);object.put("userName",username);object.put("nickName",nicke);object.put("phonenumber",phone);object.put("email",email);object.put("sex",sex);object.put("file","");object.put("remark","");} catch (Exception e) {e.printStackTrace();}// 设置 MediaType参数MediaType mediaType = MediaType.parse("application/json;charset=utf-8");// 请求体RequestBody requestBody = RequestBody.create(mediaType,object.toString());Request request = new Request.Builder().url(APIConfig.BASE_URL+"/system/user/updata") // 请求url.post(requestBody) // post 请求发送数据到服务端.addHeader("Authorization",token) 带上token 请求头.build();Call call = client.newCall(request); // 请求回调call.enqueue(new Callback() {  // 异步请求// 请求失败@Overridepublic void onFailure(Call call, IOException e) {Log.i("请求失败",e.getMessage());}// 响应成功@Overridepublic void onResponse(Call call, Response response) throws IOException {// 成功if (response.isSuccessful()) {Gson gson = new Gson();String result = response.body().string();ResponseBean responseBean = gson.fromJson(result,ResponseBean.class);String code = responseBean.getCode();if (code=="200") {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(getApplicationContext(),"用户信息修改成功:"+result,Toast.LENGTH_LONG).show();;}});}}}});}
}

activity_user_info.xml:

修改个人信息页面布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_margin="10dp"android:orientation="vertical"><RelativeLayoutandroid:layout_margin="10dp"android:layout_width="wrap_content"android:layout_height="wrap_content"><ImageButtonandroid:id="@+id/btn_back"android:layout_width="40dp"android:layout_height="40dp"android:background="@null"android:layout_alignParentLeft="true"android:src="@mipmap/top_bar_left_back1"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="用户信息"android:textStyle="bold"android:layout_centerHorizontal="true"android:layout_toRightOf="@id/btn_back"android:textColor="#000000"android:textSize="20sp"android:gravity="center"/></RelativeLayout><LinearLayoutandroid:background="@drawable/login_form_bg"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="我的头像"android:layout_marginTop="10dp"android:textSize="18sp"android:paddingRight="16dp"android:textColor="#000000"/><ImageViewandroid:id="@+id/ib_img"android:layout_width="60dp"android:layout_height="60dp"android:src="@mipmap/top_image_icon"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="15dp"android:background="#F6F5F4"/><LinearLayoutandroid:layout_marginTop="12dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="我的昵称"android:layout_marginTop="10dp"android:textSize="18sp"android:textColor="#000000"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/et_nicke"android:textSize="16sp"android:background="@null"android:layout_margin="5dp"android:hint="请输入昵称"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="15dp"android:background="#F6F5F4"/><LinearLayoutandroid:layout_marginTop="12dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="联系电话"android:layout_marginTop="10dp"android:textSize="18sp"android:textColor="#000000"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/et_phone"android:textSize="16sp"android:background="@null"android:layout_margin="5dp"android:hint="请输入你的手机号码"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="15dp"android:background="#F6F5F4"/><LinearLayoutandroid:layout_marginTop="12dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="邮箱地址"android:layout_marginTop="10dp"android:textSize="18sp"android:textColor="#000000"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/et_email"android:textSize="16sp"android:background="@null"android:layout_margin="5dp"android:hint="请输入你的邮箱地址"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="15dp"android:background="#F6F5F4"/><LinearLayoutandroid:layout_marginTop="12dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="证件信息"android:layout_marginTop="10dp"android:textSize="18sp"android:textColor="#000000"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/et_idetity"android:textSize="16sp"android:background="@null"android:layout_margin="5dp"android:hint="4405281999121411040640"/></LinearLayout><Viewandroid:layout_marginTop="15dp"android:layout_width="match_parent"android:layout_height="1dp"android:background="#F6F5F4"/><LinearLayoutandroid:layout_marginTop="12dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="你的性别"android:layout_marginTop="10dp"android:textSize="18sp"android:textColor="#000000"/><RadioGroupandroid:id="@+id/rg_sex"android:layout_marginBottom="20dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="30dp"android:orientation="horizontal"><RadioButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="男"android:layout_marginRight="40dp"android:id="@+id/rb_man"/><RadioButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="女"android:id="@+id/rb_woman"/></RadioGroup></LinearLayout></LinearLayout><Buttonandroid:id="@+id/btn_update"android:layout_marginTop="50dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="修改"android:textSize="20sp"android:textColor="#ffffff"android:background="@drawable/login_btn_bg"/><Buttonandroid:id="@+id/btn_clear"android:layout_marginTop="10dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="清空"android:textSize="20sp"android:textColor="#107FD8"android:background="@drawable/login_form_bg"/>
</LinearLayout>

公共实体类

在bean目录下新家LoginBean.class 实体类,gson解析json数据会用到

LoginBean:

public class LoginBean {/*** msg : 操作成功* code : 200* token : eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImMyYjE1YTNkLTlkNWQtNGFmZi04MGU3LTNlNWMxYTdkYzcyNSJ9.sZxcMsSvH7F50jCpTdtrv296mgq5IOI8OAo8rAXDQ4mw7KssvPsdwFcFdxHyGodfYmrsDxv0wyyEgDdl7JDxoQ*/private String msg;private String code;private String token;public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getToken() {return token;}public void setToken(String token) {this.token = token;}public LoginBean(String msg, String code, String token) {this.msg = msg;this.code = code;this.token = token;}@Overridepublic String toString() {return "UserLogin{" +"msg='" + msg + '\'' +", code=" + code +", token='" + token + '\'' +'}';}
}

个人订单

OrderActivity:

个人订单跟解析新闻数据差不多,不过个人订单属于个人隐私的数据,在请求服务端数据时,需要在okhttp中的addHeader("Authorization",token)请求头带上Authorization 标识的token值来验证请求。

public class OrderActivity extends AppCompatActivity {private Toolbar toolbar;private ListView order_listView;private OrderBean orderBean;
/*    private Handler handler = new Handler(){@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);if (msg.what==1) {String result = msg.obj.toString();Gson gson = new Gson();orderBean = gson.fromJson(result,OrderBean.class);OrderAdapter orderAdapter = new OrderAdapter();order_listView.setAdapter(orderAdapter);order_listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {Toast.makeText(getApplication(),"你点击了:"+i,Toast.LENGTH_LONG).show();}});}}};*/@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_order);toolbar = findViewById(R.id.toolbar);order_listView = findViewById(R.id.order_listView);getHttp();}private void getHttp() {// 请求参数int pageNum = 1;int pageSize = 10;int userId = 1;实例化 OkHttpClient 对象OkHttpClient client = new OkHttpClient();// 读取本地保存的token 值SharedPreferences sp = getSharedPreferences("token_data",MODE_PRIVATE);String token  =sp.getString("token","");// 创建JSONObject 对象JSONObject object = new JSONObject();try { // 带上请求体参数object.put("pageNum",1);object.put("pageSize",10);object.put("userId",1);} catch (JSONException e) {e.printStackTrace();}// 设置 MediaType参数MediaType mediaType = MediaType.parse("application/json;charset=utf-8");// 请求体RequestBody requestBody = RequestBody.create(mediaType,object.toString());String url = APIConfig.BASE_URL+"/userinfo/orders/list"+"?"+pageNum+"&"+pageSize+"&"+userId;Request request = new Request.Builder().url(url).addHeader("Authorization",token).build();// 请求回调         Call call = client.newCall(request);// 重写异步请求call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.i("onFailure",e.getMessage());}// 请求响应成功@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response.isSuccessful()) {String result = response.body().string();Log.i("请求成功",result);runOnUiThread(new Runnable() {@Overridepublic void run() {// gson解析请求到的数据Gson gson = new Gson();orderBean = gson.fromJson(result,OrderBean.class);OrderAdapter orderAdapter = new OrderAdapter();order_listView.setAdapter(orderAdapter);order_listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {Toast.makeText(getApplication(),"你点击了"+i,Toast.LENGTH_LONG).show();}});}});}}});}@Overrideprotected void onStart() {super.onStart();// 顶部标题栏toolbar.setTitle("订单列表");setSupportActionBar(toolbar);// 设置标题栏图标toolbar.setNavigationIcon(R.mipmap.top_bar_left_back);toolbar.setTitleMarginEnd(200);// 点击事件toolbar.setNavigationOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {finish();}});}public class OrderAdapter extends BaseAdapter {// item 数据@Overridepublic int getCount() {return orderBean.getData().size();}@Overridepublic Object getItem(int i) {return orderBean.getData().get(i);}@Overridepublic long getItemId(int i) {return i;}// 每项item布局@Overridepublic View getView(int i, View view, ViewGroup viewGroup) {HolderView holderView;if (view==null) {view = View.inflate(getApplicationContext(),R.layout.order_item,null);holderView = new HolderView();holderView.tv_ordernum  = view.findViewById(R.id.tv_ordernum);holderView.order_date  = view.findViewById(R.id.order_date);holderView.order_type = view.findViewById(R.id.order_type);view.setTag(holderView);} else {holderView = (HolderView) view.getTag();}holderView.order_date.setText(orderBean.getData().get(i).getCreateTime());holderView.tv_ordernum.setText(orderBean.getData().get(i).getOrderNum());holderView.order_type.setText("地铁");return view;}// 优化ListViewclass HolderView{TextView tv_ordernum;TextView order_date;TextView order_type;}}
}

基本都注释了,我们都知道在Android中不能在主线程进行网络请求等耗时操作,而且Ui控件的更新不能在工作线程中操作,所以通过 runOnUiThread这个方法来更新UI界面。当然跟新Ui还有其他方式例如:使用AsyncTaskHandler等,这里不做深究。如果在fragment中,记得通过getActivity获取当前

activity_order.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".activity.OrderActivity"><androidx.appcompat.widget.Toolbarandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/toolbar"app:titleTextColor="#fff"android:background="@color/blue"/><ListViewandroid:layout_width="match_parent"android:divider="#000"android:layout_height="wrap_content"android:id="@+id/order_listView" /></LinearLayout>

接下来就是ListView 适配器子项item布局:

order_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutandroid:padding="4dp"xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:orientation="vertical"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:background="@drawable/login_form_bg"android:orientation="vertical"android:layout_marginRight="20dp"><LinearLayoutandroid:layout_width="match_parent"android:orientation="horizontal"android:layout_height="wrap_content"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="订单编号:"/><TextViewandroid:layout_weight="1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="100000000"android:id="@+id/tv_ordernum"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="2021-03-28 23:45:34"android:id="@+id/order_date"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:orientation="horizontal"android:layout_height="wrap_content"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="订单类型:"android:layout_marginTop="10dp"android:id="@+id/order_type0"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="交通出行"android:layout_marginTop="10dp"android:id="@+id/order_type"/></LinearLayout></LinearLayout></LinearLayout>

OrderBean实体类

public class OrderBean implements Serializable {/*** msg : 操作成功* code : 200* data : [{"searchValue":null,"createBy":null,"createTime":"2020-10-24 19:23:31","updateBy":null,"updateTime":null,"remark":null,"params":{},"orderNum":"60353861","id":1,"path":"三号线","start":"珠江新城","end":"广州北站","price":8,"userName":"张三","userTel":"12345611","userId":1,"status":0},{"searchValue":null,"createBy":null,"createTime":"2020-10-24 19:25:36","updateBy":null,"updateTime":null,"remark":null,"params":{},"orderNum":"60353873","id":2,"path":"三号线","start":"珠江新城","end":"大连北站","price":8,"userName":"张三","userTel":"12345611","userId":1,"status":0}]*/private String msg;private int code;private List<OrderData> data;public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public List<OrderData> getData() {return data;}public void setData(List<OrderData> data) {this.data = data;}public static class OrderData {/*** searchValue : null* createBy : null* createTime : 2020-10-24 19:23:31* updateBy : null* updateTime : null* remark : null* params : {}* orderNum : 60353861* id : 1* path : 一号线* start : 泰德大厦* end : 大连北站* price : 8* userName : 张三* userTel : 12345611* userId : 1* status : 0*/private Object searchValue;private Object createBy;private String createTime;private Object updateBy;private Object updateTime;private Object remark;private String orderNum;private int id;private String path;private String start;private String end;private int price;private String userName;private String userTel;private int userId;private int status;public Object getSearchValue() {return searchValue;}public void setSearchValue(Object searchValue) {this.searchValue = searchValue;}public Object getCreateBy() {return createBy;}public void setCreateBy(Object createBy) {this.createBy = createBy;}public String getCreateTime() {return createTime;}public void setCreateTime(String createTime) {this.createTime = createTime;}public Object getUpdateBy() {return updateBy;}public void setUpdateBy(Object updateBy) {this.updateBy = updateBy;}public Object getUpdateTime() {return updateTime;}public void setUpdateTime(Object updateTime) {this.updateTime = updateTime;}public Object getRemark() {return remark;}public void setRemark(Object remark) {this.remark = remark;}public String getOrderNum() {return orderNum;}public void setOrderNum(String orderNum) {this.orderNum = orderNum;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}public String getStart() {return start;}public void setStart(String start) {this.start = start;}public String getEnd() {return end;}public void setEnd(String end) {this.end = end;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getUserTel() {return userTel;}public void setUserTel(String userTel) {this.userTel = userTel;}public int getUserId() {return userId;}public void setUserId(int userId) {this.userId = userId;}public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public OrderData(String createTime, String orderNum) {this.createTime = createTime;this.orderNum = orderNum;}}
}

【Android项目实战 | 从零开始写app(十三)】实现用户中心模块清除token退出登录信息修改等功能相关推荐

  1. 【Android项目实战 | 从零开始写app(十二)】实现app首页智慧服务热门推荐热门主题、新闻

    说在前面,由于各种adapter,xml布局,bean实体类,Activity,也为了让看懂,代码基本都是"简单粗暴直接不好看",没啥okhttp和util工具类之类的封装,本篇幅 ...

  2. 【Android项目实战 | 从零开始写app (六) 】用TabLayout+ViewPager搭建App 框架主页面底部导航栏

    本篇实现效果: 搭建app框架的方式有很多,本节主要用TabLayout+ViewPager搭建App框架,这种方式简单易实现,在主页中加载Fragment碎片,实现不同功能页面的切换效果图如下: 文 ...

  3. 【Android项目实战 | 从零开始写app一一智慧服务】完结篇系列导航篇、源代码

    目录 文章介绍 涉及知识 系列汇总 项目源代码 文章介绍 本系列小文是一个简单的Android app项目实战,对于刚入门Android 的初学者来说,基础学完了,但是怎么综合的去写一个小app,可能 ...

  4. STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)

    STS创建Spring Boot项目实战(Rest接口.数据库.用户认证.分布式Token JWT.Redis操作.日志和统一异常处理) 1.项目创建 1.新建工程 2.选择打包方式,这边可以选择为打 ...

  5. Android项目实战:账本APP开发

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 Java项目实战:账本APP服务 ...

  6. 基于eclipse的android项目实战—博学谷(十三)水平滑动广告栏界面

    本项目是用eclipse软件编写,经过我的亲自实践,其真实有效,希望能给您有所帮助

  7. 基于eclipse的android项目实战—博学谷(五)“我”的模块

    本项目是用eclipse软件编写,经过我的亲自实践,其真实有效,希望能给您有所帮助

  8. 基于eclipse的android项目实战—博学谷(二十三)其他功能

    本项目是用eclipse软件编写,经过我的亲自实践,其真实有效,希望能给您有所帮助 项目版本:android5.1.1 ADT版本:23.0.6 SDK版本:24.4.1 运行模拟器:夜神模拟器 若有 ...

  9. 基于eclipse的android项目实战—博学谷(十九)播放不同视频(本地视频)

    BoXueGu资源下载链接: https://download.csdn.net/download/hyh/19477319 BoXueGu图片资源下载(免费): https://yuyunyaohu ...

最新文章

  1. 原生与html,解析原生与html之间进行的一些关联
  2. css3宽度变大动画_学所 前端 | HTML5+CSS3
  3. CentOS下安装semanage
  4. Centos7安装防火墙firewall
  5. Angular form控件原生HTML代码里ng-reflect-form属性和其值的生成时机
  6. 【解决】ERROR in xxx.js from UglifyJs
  7. mysql route mycat_mycat
  8. Kali Linux 网络扫描秘籍 第六章 拒绝服务(一)
  9. 卢伟冰:“四摄小金刚”的诞生是为了让更多用户享受全场景拍摄的乐趣
  10. 韩国Hana银行将建立试点验证CBDC技术
  11. 20200317_决策树预测贷款申请
  12. 转:多线程--六种多线程方法解决UI线程阻塞
  13. CodeGear 出品 Delphi for PHP
  14. RIME中州韵输入法词库扩充(搜狗词库,QQ拼音词库,清华词库,拆字词库U模式等)
  15. prcs6汉化补丁怎么替换_美少女万华镜5汉化版百度云下载-美少女万华镜5汉化版百度网盘下载-附全cg...
  16. 关于影响力章节的读后感:第二章
  17. 如何查看计算机的网络网址,怎么查看电脑IP地址_如何查看电脑IP地址?-192路由网...
  18. 计算机绘图如何设置精度2007,excel2007饼图百分比精确度如何设置
  19. keystore生成签名证书
  20. 如何在今日头条做推广?今日头条推广怎么样?

热门文章

  1. 显示器 Linux 性能 18 (一个命令行工具传递)
  2. python解析mdf或mf4文件利器---asammdf
  3. 数仓指标一致性以及核对方法
  4. 做好这15个事项,工作起来事半功倍~
  5. 无线网络工程建设、升级及维护要注意什么——TFN-100A系列天馈线频谱测试仪
  6. 拳皇97模拟器没有换面
  7. Android按键事件——上层与驱动的映射
  8. iOS给图片(其他view) 添加点击事件
  9. NVIDIA CUDA初级教程(P11)CUDA程序基本优化
  10. 【理想流】项目管理本质论 .