Python 基础-项目实战-day 13 Android客户端开发(项目完结)

一、项目介绍

Python 实现博客服务端,客户端分别 PC Web端 和 手机 Android端

1.项目来源

廖雪峰老师
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000

2.项目 Github

https://github.com/sufadi/python3-webapp-Su/tree/master/android

3.运行效果

Android 客户端

二、Android 端实现

1.建立一个简单的 ListView 展示

1.1 布局

ListView 显示数据

<LinearLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.su.androidblog.MainActivity"
    android:orientation="vertical">

    <TextView 
        android:text="Python博客开发Android客户端"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        />

    <ListView
        android:id="@+id/listView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>
1.2 List的初始化
private ListView mListView;

    private void initValue() {
        mContext = this;
        mBlogs = new ArrayList<Blogs>();

        mCustomAdapter = new CustomAdapter<Blogs>(mBlogs);

        mCustomAdapter.setLayoutView(this);
        mListView.setAdapter(mCustomAdapter);

    }

    @Override
    public <T> View setView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_blog_list, null);

            holder = new ViewHolder();
            holder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
            holder.tv_content = (TextView) convertView.findViewById(R.id.tv_content);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Blogs mBlog = mBlogs.get(position);

        holder.tv_title.setText(mBlog.name);
        holder.tv_content.setText(mBlog.summary);

        return convertView;
    }

2.Python 数据获取

这里使用第三方库 volley.jar

2.1 Python 服务端 API 接口

获取应用列表数据

这里写图片描述

@get('/api/blogs/all')
def api_blogs(*, page='1'):
    blogs = yield from Blog.findAll(orderBy='created_at desc')
    return dict(blogs=blogs)
2.2 volley 的使用和网络接口
=============================================================================
// 初始化网络
RequestManager.init(this);

=============================================================================
// 服务端地址,注意下面的描述
public class NetConfig {

    /**
     * 因为http://127.0.0.1:9000/ 访问PC本地机启动的服务器时会报错, 因为android会默认访问它本身 故使用
     * http://10.0.2.2:9000/
     */
    public static final String HOST_LAVA_POWERSAVE = "http://10.0.2.2:9000";

    public static final String URL_BLOG_LIST = HOST_LAVA_POWERSAVE + "/api/blogs/all";
=============================================================================    
// API 接口
public class ApiRequests {

    private static ApiRequests mInstance;

    public static ApiRequests getInstance() {
        if (mInstance == null) {
            mInstance = new ApiRequests();
        }
        return mInstance;
    }

    public void getBlogs(Context context, Listener<?> listener, ErrorListener errorListener) {
        String url = NetConfig.URL_BLOG_LIST;

        GsonRequest<BlogsHead> request = new GsonRequest<BlogsHead>(Method.GET, url, BlogsHead.class, (Listener<BlogsHead>) listener, errorListener);
        RequestManager.getRequestQueue().add(request);
    }
}
=============================================================================
客户端调用
    public void updateBlogs() {
        Log.d(TAG, "updateBlogs");

        ApiRequests.getInstance().getBlogs(mContext, new Listener<BlogsHead>() {

            @Override
            public void onResponse(BlogsHead response) {
                mBlogs.clear();
                mBlogs = response.blogs;
                mHandler.sendEmptyMessage(UPDATE_UI);
            }

        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.d(TAG, error.toString());
            }

        });
    }
2.1 数据结果

如下的,看起很凌乱对不对,可以使用 Json格式转换,这样看得懂一些

https://www.bejson.com/

这里写图片描述

Json格式化的数据如下

{
    "blogs": [{
        "id": "001515633814914b02515cf6b284ec1b1eef741d32434ab000",
        "user_id": "00151558881765135c1d8940a8f4bf19bb2c836eccdb707000",
        "user_name": "123",
        "user_image": "http://www.gravatar.com/avatar/b2d7d2d13aed54c2ed7feb538b382b42?d=mm&s=120",
        "name": "Create Blog",
        "summary": "Tursday",
        "content": "Good day",
        "created_at": 1515630000.0
    }, {
        "id": "0015156358419219e13a79d61584f56bb7242064783e9ff000",
        "user_id": "00151558881765135c1d8940a8f4bf19bb2c836eccdb707000",
        "user_name": "123",
        "user_image": "http://www.gravatar.com/avatar/b2d7d2d13aed54c2ed7feb538b382b42?d=mm&s=120",
        "name": "sdf",
        "summary": "sdaf",
        "content": "asfdasf",
        "created_at": 1515640000.0
    }, {
        "id": "0015156359616096a8f75b1490348b69857777919992a7d000",
        "user_id": "00151558881765135c1d8940a8f4bf19bb2c836eccdb707000",
        "user_name": "123",
        "user_image": "http://www.gravatar.com/avatar/b2d7d2d13aed54c2ed7feb538b382b42?d=mm&s=120",
        "name": "Good old days",
        "summary": "dreams",
        "content": "We have all got our \"good old days\" tucked away inside our hearts, and we return to them in dreams like cats to favorite armchairs.",
        "created_at": 1515640000.0
    }, {
        "id": "001515636301092f26271f023994d07863fe52a164781d8000",
        "user_id": "00151558881765135c1d8940a8f4bf19bb2c836eccdb707000",
        "user_name": "123",
        "user_image": "http://www.gravatar.com/avatar/b2d7d2d13aed54c2ed7feb538b382b42?d=mm&s=120",
        "name": "Good old days",
        "summary": "dreams",
        "content": "We have all got our \"good old days\" tucked away inside our hearts, and we return to them in dreams like cats to favorite armchairs.",
        "created_at": 1515640000.0
    }, {
        "id": "001515758667406801b75382e684a4891b97cb12b566760000",
        "user_id": "00151558881765135c1d8940a8f4bf19bb2c836eccdb707000",
        "user_name": "123",
        "user_image": "http://www.gravatar.com/avatar/b2d7d2d13aed54c2ed7feb538b382b42?d=mm&s=120",
        "name": "Hello world",
        "summary": "Hello",
        "content": "Python study",
        "created_at": 1515760000.0
    }, {
        "id": "1",
        "user_id": "1",
        "user_name": "123",
        "user_image": "safdsadfsdf",
        "name": "234",
        "summary": "adsffasdf",
        "content": "fasdfsadfsa",
        "created_at": 123123000.0
    }]
}
3 解析数据库

这里使用 GSON

根据上述的数据,定义下面的类
=========================================================
package com.su.androidblog.bean;

import java.util.List;

public class BlogsHead {

    public List<Blogs> blogs;

}
根据上述的数据,定义下面的类
=========================================================
package com.su.androidblog.bean;

public class Blogs {

    /*
     * "blogs": [{ "id": "001515758667406801b75382e684a4891b97cb12b566760000",
     * "user_id": "00151558881765135c1d8940a8f4bf19bb2c836eccdb707000",
     * "user_name": "123", "user_image":
     * "http://www.gravatar.com/avatar/b2d7d2d13aed54c2ed7feb538b382b42?d=mm&s=120"
     * , "name": "Hello world", "summary": "Hello", "content": "Python study",
     * "created_at": 1515760000.0
     */

    public String id;

    public String user_id;

    public String user_name;

    public String user_image;

    public String name;

    public String summary;

    public String content;

    public String created_at;
}
=========================================================
ApiRequests.java
    public void getBlogs(Context context, Listener<?> listener, ErrorListener errorListener) {
        String url = NetConfig.URL_BLOG_LIST;

        GsonRequest<BlogsHead> request = new GsonRequest<BlogsHead>(Method.GET, url, BlogsHead.class, (Listener<BlogsHead>) listener, errorListener);
        RequestManager.getRequestQueue().add(request);
    }
=========================================================
    ApiRequests.getInstance().getBlogs(mContext, new Listener<BlogsHead>() {

            @Override
            public void onResponse(BlogsHead response) {
                mBlogs.clear();
                mBlogs = response.blogs;
                mHandler.sendEmptyMessage(UPDATE_UI);
            }
=========================================================
4 显示数据
    mHandler.sendEmptyMessage(UPDATE_UI);


    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case UPDATE_UI:
                mCustomAdapter.updateData((ArrayList<Blogs>) mBlogs);
                break;

            default:
                break;
            }

        }
    };
5 小结

本项目的 GitHub
https://github.com/sufadi/python3-webapp-Su

Python 应该还有其他用途吧,打算学下 Python 写的爬虫项目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值