淘忆项目之主题界面的修正归纳
主题界面是后台推送的内容,以在数据库中插入相关数据然后显示在主题界面,有期刊号和时间,图片还有链接组成。实现点击主题后跳转html页面查看详细信息,功能简单。
第一步:用photoshop来设计界面。
第二步,设计数据库,先用没有写好的网址先代替。
第三步:服务器端的操作
从数据库查询数据,然后返回给客户端,同样采用mvc模型。
Com.elaine.theme.service:
package com.elaine.theme.service;
import java.util.List;
import java.util.Map;
public interface ThemeService {
public List<Map<String, Object>> listThing(String themeIssue); //这个方法用于将内容都查询出来
}
Com.elaine.theme.dao:
package com.elaine.theme.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.elaine.jdbc.JdbcUtils;
import com.elaine.theme.service.ThemeService;
public class ThemeDao implements ThemeService{
JdbcUtils jdbcUtils;
public ThemeDao() {
// TODO Auto-generated constructor stub
jdbcUtils=new JdbcUtils();
}
@Override
public List<Map<String, Object>> listThing(String themeIssue) {
// TODO Auto-generated method stub
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
String sql = "select * from themeInfo where (1=1) ";
StringBuffer buffer = new StringBuffer(sql);
List<Object> params = new ArrayList<Object>();
if (themeIssue != null) {
buffer.append(" and themeIssue like ? ");
params.add("%" + themeIssue + "%");
}
try {
jdbcUtils.getConnection();
list = jdbcUtils.findMoreResult(buffer.toString(), params); //多条语句查询
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
jdbcUtils.releaseConn();
}
return list;
}
}
com.elaine.theme.action
package com.elaine.theme.action;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.elaine.theme.dao.ThemeDao;
import com.elaine.theme.service.ThemeService;
import com.elaine.tools.jsonTool;
public class ThemeAction extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
private ThemeService service;
/**
* Constructor of the object.
*/
public ThemeAction() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to
* post.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
String themeIssue = (request.getParameter("themeIssue")) == null ? ""
: request.getParameter("themeIssue");
List<Map<String, Object>> list = service.listThing(themeIssue);
String jsonString = jsonTool.creataJsonString("theme", list); //返回数据进行json封装,这用到了jsonArray
out.print(jsonString);
out.flush();
out.close();
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException
* if an error occurs
*/
public void init() throws ServletException {
// Put your code here
service = new ThemeDao();
}
}
第四步:客户端的数据整理显示。
首先是将servelt的内容写好:
public static String getThemeUrl() {
return URL + "/servlet/ThemeAction";
}
然后是布局文件:
采用RecyclerView的形式出现,所以先建立item_theme.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:background="#fff"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/tv_journal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="第3期"
android:textColor="#707070"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_journalTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="2016年7月17日 15:34"
android:textColor="#77707070"
android:textSize="12sp" />
</LinearLayout>
<ImageView
android:id="@+id/iv_journalPic"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginBottom="10dp"
android:scaleType="fitXY" />
<View
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="#f8f8f8" />
</LinearLayout>
然后写ThemeItemAdapter.java的内容:
这里需要先写一下公用数据,建立一个app,属于Application,然后初始化ImageLoader,来避免OOM。
package com.elainetaylor.blog.app;
import android.app.Application;
import android.graphics.Bitmap;
import android.os.Environment;
import com.elainetaylor.blog.R;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.UsingFreqLimitedMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import java.io.File;
/**
* Created by Eaine Taylor on 2016/8/16.
*/
public class app extends Application {
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
initImageLoader();
}
private void initImageLoader() {
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
this)
.memoryCacheExtraOptions(480, 800)
.threadPoolSize(3)
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
.memoryCacheSize(2 * 1024 * 1024)
.discCacheSize(50 * 1024 * 1024)
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.discCacheFileCount(100)
.discCache(new UnlimitedDiscCache(new File(Environment.getExternalStorageDirectory() + "/com.elaine.Blog/imgCache"))) //缓存到本地地址
.defaultDisplayImageOptions(getDisplayOptions())
.imageDownloader(new BaseImageDownloader(this, 5 * 1000, 30 * 1000))
.writeDebugLogs()
.build();
ImageLoader.getInstance().init(config);
}
private DisplayImageOptions getDisplayOptions() {
DisplayImageOptions options;
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.mipmap.pic_default)
.showImageForEmptyUri(R.mipmap.pic_default)
.showImageOnFail(R.mipmap.pic_default)
.cacheInMemory(true)//缓存到内存
.cacheOnDisc(true) //缓存到磁盘
.considerExifParams(true)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
.bitmapConfig(Bitmap.Config.RGB_565)
.resetViewBeforeLoading(true)
.displayer(new FadeInBitmapDisplayer(100))
.build();
return options;
}
}
然后是ThemeItemAdapter的内容:
package com.elainetaylor.blog.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.elainetaylor.blog.R;
import com.elainetaylor.blog.listener.OnItemClickListener;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.util.List;
/**
* Created by Eaine Taylor on 2016/7/20.
*/
public class ThemeItemAdapter extends RecyclerView.Adapter<ThemeItemAdapter.ThemeViewHolder> {
private List<String> journal;
private List<String> journalTime;
private List<String> pic;
private Context context;
private OnItemClickListener listener;
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
public ThemeItemAdapter(List<String> journal, List<String> journalTime, List<String> pic, Context context) {
this.journal = journal;
this.journalTime = journalTime;
this.pic = pic;
this.context = context;
}
@Override
public ThemeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //设置布局文件
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_theme, parent, false);
ThemeViewHolder holder = new ThemeViewHolder(view, listener);
return holder;
}
//将图片以ImageLoader的方式展现,可以避免OOM
@Override
public void onBindViewHolder(ThemeViewHolder holder, int position) {
holder.tvJournal.setText(journal.get(position));
holder.tvJournalTime.setText(journalTime.get(position));
ImageLoader loader=ImageLoader.getInstance();
loader.displayImage(pic.get(position),holder.nivJournalPic);
}
@Override
public int getItemCount() {
return journal.size();
}
//初始化控件和设置监听
class ThemeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tvJournal, tvJournalTime;
public ImageView nivJournalPic;
public OnItemClickListener listener;
public ThemeViewHolder(View itemView, OnItemClickListener listener) {
super(itemView);
tvJournal = (TextView) itemView.findViewById(R.id.tv_journal);
tvJournalTime = (TextView) itemView.findViewById(R.id.tv_journalTime);
nivJournalPic = (ImageView) itemView.findViewById(R.id.iv_journalPic);
this.listener = listener;
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (listener != null) {
listener.OnclickItemClick(view, getPosition());
}
}
}
}
这里需要重写OnItemClickListener,是点击出现效果:
package com.elainetaylor.blog.listener;
import android.view.View;
/**
* Created by Eaine Taylor on 2016/7/24.
*这是建立一个Interface 来实现OnItemClickLister
*/
public interface OnItemClickListener {
public void OnclickItemClick(View view, int positon);
}
然后是写fragment_theme.xml的内容,就是一个RecyclerView控件:
<FrameLayout 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:background="#f8f8f8"
tools:context="com.elainetaylor.blog.ui.fragment.ThemeFragment">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_theme"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</FrameLayout>
然后是ThemeFragment.java文件的内容:
package com.elainetaylor.blog.ui.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.elainetaylor.blog.R;
import com.elainetaylor.blog.adapter.ThemeItemAdapter;
import com.elainetaylor.blog.common.UrlUtils;
import com.elainetaylor.blog.listener.OnItemClickListener;
import com.elainetaylor.blog.ui.activity.ThemeUrlActivity;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class ThemeFragment extends Fragment implements OnItemClickListener {
private List<String> journal;
private List<String> journalTime;
private List<String> pic;
private List<String> journalUrl;
private RecyclerView rvTheme;
private ThemeItemAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_theme, container, false);
rvTheme = (RecyclerView) view.findViewById(R.id.rv_theme);
init(); //初始化数据
initData();
return view;
}
public void init() {
journal = new ArrayList<String>();
journalTime = new ArrayList<String>();
pic = new ArrayList<String>();
journalUrl = new ArrayList<String>();
}
public void initData() {
RequestQueue queue = Volley.newRequestQueue(getActivity());
StringRequest request = new StringRequest(Request.Method.POST, UrlUtils.getThemeUrl(), new Response.Listener<String>() {
@Override
public void onResponse(String s) {
try { //解析由服务器端传来的数据
JSONObject object1 = new JSONObject(s);
JSONArray array = object1.getJSONArray("theme");
for (int i = array.length() - 1; i >= 0; i--) {
JSONObject object = array.getJSONObject(i);
journal.add(object.getString("themeIssue"));
journalTime.add(object.getString("themeTime"));
pic.add(UrlUtils.getPicUrl() + object.getString("themePic"));
journalUrl.add(object.getString("themeUrl"));
}
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
rvTheme.setLayoutManager(manager);
adapter = new ThemeItemAdapter(journal, journalTime, pic, getActivity());
rvTheme.setAdapter(adapter);
//设置监听
adapter.setOnItemClickListener(ThemeFragment.this);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
System.out.println(volleyError.toString());
}
});
queue.add(request);
}
//将数据传给ThemeUrlActivity,就是网址
@Override
public void OnclickItemClick(View view, int positon) {
Intent intent = new Intent(getActivity(), ThemeUrlActivity.class);
intent.putExtra("goThemeUrl", journalUrl.get(positon));
startActivity(intent);
}
}