学习进度条

今日所花时间:一小时
今日代码量:100行
博客量:2篇
了解到的知识点:
深入学习androidStudio 完成课堂测试,实现手机端的政策模糊查询

我没有使用AndriodStudio内置的数据库SQLite,而是使用后端服务springboot,创建安全的API端点,在Android中使用Retrofit访问API完成数据库的连接和功能实现

springboot后端代码

实体类代码

package com.example.search.pojo;

import jakarta.persistence.*;
import java.util.Date;

@Entity
@Table(name = "policy")
public class policy {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "type")
    private String type;

    @Column(name = "category")
    private String category;

    @Column(name = "range")
    private String range;

    @Column(name = "document")
    private String document;

    @Column(name = "form")
    private String form;

    @Column(name = "organ")
    private String organ;

    @Column(name = "viadata")
    private Date viadata;

    @Column(name = "pubdata")
    private Date pubdata;

    @Column(name = "perdata")
    private Date perdata;

    @Column(name = "field")
    private String field;

    @Column(name = "theme")
    private String theme;

    @Column(name = "keyword")
    private String keyword;

    @Column(name = "superior")
    private String superior;

    @Column(name = "precursor")
    private String precursor;

    @Column(name = "succeed")
    private String succeed;

    @Column(name = "state")
    private String state;

    @Column(name = "text", columnDefinition = "longtext")
    private String text;

    @Column(name = "pdf")
    private String pdf;

    @Column(name = "redundancy")
    private String redundancy;

    @Column(name = "rank")
    private String rank;

    @Column(name = "policykey", columnDefinition = "text")
    private String policykey;

    @Column(name = "newrank")
    private String newrank;

    @Column(name = "year")
    private String year;

    @Column(name = "newkey")
    private String newkey;

    @Column(name = "secondtheme")
    private String secondtheme;

    @Column(name = "allsum")
    private Integer allsum;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getRange() {
        return range;
    }

    public void setRange(String range) {
        this.range = range;
    }

    public String getDocument() {
        return document;
    }

    public void setDocument(String document) {
        this.document = document;
    }

    public String getForm() {
        return form;
    }

    public void setForm(String form) {
        this.form = form;
    }

    public String getOrgan() {
        return organ;
    }

    public void setOrgan(String organ) {
        this.organ = organ;
    }

    public Date getViadata() {
        return viadata;
    }

    public void setViadata(Date viadata) {
        this.viadata = viadata;
    }

    public Date getPubdata() {
        return pubdata;
    }

    public void setPubdata(Date pubdata) {
        this.pubdata = pubdata;
    }

    public Date getPerdata() {
        return perdata;
    }

    public void setPerdata(Date perdata) {
        this.perdata = perdata;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public String getTheme() {
        return theme;
    }

    public void setTheme(String theme) {
        this.theme = theme;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public String getSuperior() {
        return superior;
    }

    public void setSuperior(String superior) {
        this.superior = superior;
    }

    public String getPrecursor() {
        return precursor;
    }

    public void setPrecursor(String precursor) {
        this.precursor = precursor;
    }

    public String getSucceed() {
        return succeed;
    }

    public void setSucceed(String succeed) {
        this.succeed = succeed;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getPdf() {
        return pdf;
    }

    public void setPdf(String pdf) {
        this.pdf = pdf;
    }

    public String getRedundancy() {
        return redundancy;
    }

    public void setRedundancy(String redundancy) {
        this.redundancy = redundancy;
    }

    public String getRank() {
        return rank;
    }

    public void setRank(String rank) {
        this.rank = rank;
    }

    public String getPolicykey() {
        return policykey;
    }

    public void setPolicykey(String policykey) {
        this.policykey = policykey;
    }

    public String getNewrank() {
        return newrank;
    }

    public void setNewrank(String newrank) {
        this.newrank = newrank;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getNewkey() {
        return newkey;
    }

    public void setNewkey(String newkey) {
        this.newkey = newkey;
    }

    public String getSecondtheme() {
        return secondtheme;
    }

    public void setSecondtheme(String secondtheme) {
        this.secondtheme = secondtheme;
    }

    public Integer getAllsum() {
        return allsum;
    }

    public void setAllsum(Integer allsum) {
        this.allsum = allsum;
    }
}

Controller层(SelectController)

package com.example.search.controller;

import com.example.search.mapper.SelectMapper;

import com.example.search.pojo.policy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;


@RestController
@RequestMapping("/api")
public class select{

    @Autowired
    private SelectMapper selectMapper;

    @GetMapping("/searchPolicies")
    @Transactional(readOnly = true)
    public ResponseEntity<List<policy>> searchPolicies(
            @RequestParam String keyword,
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String organ,
            @RequestParam(required = false) String organNot) {

        try {
            List<policy> policies = selectMapper.findByNameContainingOrKeywordContaining(
                    keyword,
                    startDate,
                    organ,
                    organNot);
            return ResponseEntity.ok(policies);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    @GetMapping("/policy/{id}")
    @Transactional(readOnly = true)
    public ResponseEntity<policy> showPolicyFullText(@PathVariable Long id) {
        try {
            policy policy = selectMapper.findById(id);
            if (policy != null) {
                return ResponseEntity.ok(policy);
            }
            return ResponseEntity.notFound().build();
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }
    
}

mapper层(selectMapper)

package com.example.search.mapper;

import com.example.search.pojo.PolicyType;
import com.example.search.pojo.policy;
import org.apache.ibatis.annotations.*;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Mapper
public interface SelectMapper {
    @SelectProvider(type = PolicySqlProvider.class, method = "findByNameContainingOrKeywordContaining")
    @Transactional(readOnly = true)
    List<policy> findByNameContainingOrKeywordContaining(
            @Param("keyword") String keyword,
            @Param("startDate") String startDate,
            @Param("organ") String organ,
            @Param("organNot") String organNot);

    @Select("SELECT * FROM policy WHERE id = #{id}")
    @Transactional(readOnly = true)
    policy findById(Long id);
}

AndroidStudio代码

创建与springboot的API连接
ApiService

package com.example.day0321search;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;

import java.util.List;

public interface ApiService {
    @GET("/api/searchPolicies")
    Call<List<Policy>> searchPolicies(@Query("keyword") String keyword);

    @GET("/api/policy/{id}")
    Call<Policy> getPolicyById(@Path("id") Long id);
}

实体类

package com.example.day0321search;


import java.util.Date;

public class Policy {
    private Long id;
    private String name;
    private String type;
    private String category;
    private String range;
    private String document;
    private String form;
    private String organ;
    private Date viadata;
    private Date pubdata;
    private Date perdata;
    private String field;
    private String theme;
    private String keyword;
    private String superior;
    private String precursor;
    private String succeed;
    private String state;
    private String text;
    private String pdf;
    private String redundancy;
    private String rank;
    private String policykey;
    private String newrank;
    private String year;
    private String newkey;
    private String secondtheme;
    private Integer allsum;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getRange() {
        return range;
    }

    public void setRange(String range) {
        this.range = range;
    }

    public String getDocument() {
        return document;
    }

    public void setDocument(String document) {
        this.document = document;
    }

    public String getForm() {
        return form;
    }

    public void setForm(String form) {
        this.form = form;
    }

    public String getOrgan() {
        return organ;
    }

    public void setOrgan(String organ) {
        this.organ = organ;
    }

    public Date getViadata() {
        return viadata;
    }

    public void setViadata(Date viadata) {
        this.viadata = viadata;
    }

    public Date getPubdata() {
        return pubdata;
    }

    public void setPubdata(Date pubdata) {
        this.pubdata = pubdata;
    }

    public Date getPerdata() {
        return perdata;
    }

    public void setPerdata(Date perdata) {
        this.perdata = perdata;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public String getTheme() {
        return theme;
    }

    public void setTheme(String theme) {
        this.theme = theme;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public String getSuperior() {
        return superior;
    }

    public void setSuperior(String superior) {
        this.superior = superior;
    }

    public String getPrecursor() {
        return precursor;
    }

    public void setPrecursor(String precursor) {
        this.precursor = precursor;
    }

    public String getSucceed() {
        return succeed;
    }

    public void setSucceed(String succeed) {
        this.succeed = succeed;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getPdf() {
        return pdf;
    }

    public void setPdf(String pdf) {
        this.pdf = pdf;
    }

    public String getRedundancy() {
        return redundancy;
    }

    public void setRedundancy(String redundancy) {
        this.redundancy = redundancy;
    }

    public String getRank() {
        return rank;
    }

    public void setRank(String rank) {
        this.rank = rank;
    }

    public String getPolicykey() {
        return policykey;
    }

    public void setPolicykey(String policykey) {
        this.policykey = policykey;
    }

    public String getNewrank() {
        return newrank;
    }

    public void setNewrank(String newrank) {
        this.newrank = newrank;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getNewkey() {
        return newkey;
    }

    public void setNewkey(String newkey) {
        this.newkey = newkey;
    }

    public String getSecondtheme() {
        return secondtheme;
    }

    public void setSecondtheme(String secondtheme) {
        this.secondtheme = secondtheme;
    }

    public Integer getAllsum() {
        return allsum;
    }

    public void setAllsum(Integer allsum) {
        this.allsum = allsum;
    }
}

RetrofitClient

package com.example.day0321search;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.util.concurrent.TimeUnit;

public class RetrofitClient {
    private static final String BASE_URL = "http://192.168.188.118:8080/";//192.168.188.118写你自己加入的局域网(确保手机和开发电脑在同一局域网下)
    private static Retrofit retrofit = null;

    public static ApiService getApiService() {
        if (retrofit == null) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .readTimeout(15, TimeUnit.SECONDS)
                    .writeTimeout(15, TimeUnit.SECONDS)
                    .addInterceptor(loggingInterceptor)
                    .build();

            // 创建一个宽松模式的Gson实例
            Gson gson = new GsonBuilder()
                    .setLenient()
                    .create();

            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .client(client)
                    .build();
        }
        return retrofit.create(ApiService.class);
    }
}

MainActivity

package com.example.day0321search;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.io.IOException;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {
    private EditText searchInput;
    private RecyclerView policyRecyclerView;
    private PolicyAdapter policyAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        searchInput = findViewById(R.id.searchInput);
        policyRecyclerView = findViewById(R.id.policyRecyclerView);
        policyRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        findViewById(R.id.searchButton).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                searchPolicies();
            }
        });
    }

    private void searchPolicies() {
        String keyword = searchInput.getText().toString();
        ApiService apiService = RetrofitClient.getApiService();
        Call<List<Policy>> call = apiService.searchPolicies(keyword);
        call.enqueue(new Callback<List<Policy>>() {
            @Override
            public void onResponse(Call<List<Policy>> call, Response<List<Policy>> response) {
                if (response.isSuccessful() && response.body() != null) {
                    policyAdapter = new PolicyAdapter(response.body());
                    policyRecyclerView.setAdapter(policyAdapter);
                } else {
                    try {
                        Log.e("MainActivity", "Response error: " + response.errorBody().string());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "No policies found", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<List<Policy>> call, Throwable t) {
                Log.e("MainActivity", "Network error", t);
                Toast.makeText(MainActivity.this, "Network error", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

PolicyAdapter查询政策操作

package com.example.day0321search;

import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.PolicyViewHolder> {
    private List<Policy> policyList;

    public PolicyAdapter(List<Policy> policyList) {
        this.policyList = policyList;
    }

    @NonNull
    @Override
    public PolicyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_policy, parent, false);
        return new PolicyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull PolicyViewHolder holder, int position) {
        Policy policy = policyList.get(position);
        holder.policyName.setText(policy.getName());

        // 设置点击事件
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(v.getContext(), PolicyDetailActivity.class);
                intent.putExtra("policyId", policy.getId());
                v.getContext().startActivity(intent);
            }
        });
    }

    @Override
    public int getItemCount() {
        return policyList.size();
    }

    public static class PolicyViewHolder extends RecyclerView.ViewHolder {
        TextView policyName;

        public PolicyViewHolder(@NonNull View itemView) {
            super(itemView);
            policyName = itemView.findViewById(R.id.policyName);
        }
    }
}

PolicyDatailActivity(政策细节展示)

package com.example.day0321search;

import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import androidx.appcompat.app.AppCompatActivity;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class PolicyDetailActivity extends AppCompatActivity {
    private WebView policyWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_policy_detail);

        policyWebView = findViewById(R.id.policyWebView);
        // 设置 WebView 客户端,确保链接在 WebView 中打开
        policyWebView.setWebViewClient(new WebViewClient());

        Long policyId = getIntent().getLongExtra("policyId", -1);

        if (policyId != -1) {
            loadPolicyDetail(policyId);
        }
    }

    private void loadPolicyDetail(Long policyId) {
        ApiService apiService = RetrofitClient.getApiService();
        Call<Policy> call = apiService.getPolicyById(policyId);
        call.enqueue(new Callback<Policy>() {
            @Override
            public void onResponse(Call<Policy> call, Response<Policy> response) {
                if (response.isSuccessful() && response.body() != null) {
                    String htmlContent = response.body().getText();
                    // 加载 HTML 内容到 WebView
                    policyWebView.loadDataWithBaseURL(null, htmlContent, "text/html", "UTF-8", null);
                }
            }

            @Override
            public void onFailure(Call<Policy> call, Throwable t) {
                // Handle failure
            }
        });
    }
}

APP页面设计

activity_main.xml(主页面)

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">
    <!-- 标题 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="科技政策查询系统"
        android:textSize="24sp"
        android:textStyle="bold"
        android:layout_gravity="center_horizontal"
        android:paddingTop="20dp"
        android:paddingBottom="16dp"/>

    <!-- 搜索输入框 -->
    <EditText
        android:id="@+id/searchInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入政策关键字"
        android:inputType="text"
        android:maxLines="1"
        android:minHeight="48dp" />

    <!-- 搜索按钮 -->
    <Button
        android:id="@+id/searchButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="搜索" />

    <!-- 政策列表 -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/policyRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="16dp"
        tools:listitem="@layout/item_policy" />

</LinearLayout>

item_policy.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="wrap_content"
    android:orientation="vertical"
    android:padding="8dp"
    android:background="?attr/selectableItemBackground"
    android:clickable="true"
    android:focusable="true">

    <!-- 政策名称 -->
    <TextView
        android:id="@+id/policyName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:text="政策名称"
        android:textColor="@android:color/black" />

    <!-- 分割线 -->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="8dp"
        android:background="@android:color/darker_gray" />

</LinearLayout>

activity_policy_detail.xml(政策全全文展示)

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:padding="16dp"
    tools:context=".PolicyDetailActivity">


    <!-- 使用 WebView 显示政策全文 -->
    <WebView
        android:id="@+id/policyWebView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</ScrollView>
posted @ 2025-03-21 21:21  haoyinuo  阅读(29)  评论(0)    收藏  举报