热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android新闻App的本地服务器搭建教程

本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。

如今的APP许多都是要联网获取数据的,比如新闻客户端,如果想要尝试下这个流程的话,那么就需要有服务器和数据库了。在服务器上搭建各种环境是十分繁琐的,所以我们可以选择搭建一个本地服务器,然后在手机端获取其数据库内的数据。

这里选用XAMPP
XAMPP 是一个整合型的Apache套件,包含Apache、MySQL、PHP、PERL,可以一键式搭建起开发环境,推荐初学者使用。官方网址——https://www.apachefriends.org/zh_cn/index.html

软件开启后的界面是:

这里写图片描述

这里点击start开启Apache和MySQL就好,点击admin可以进入控制界面。

首先进入phpmyadmin界面,新建一个数据库 news,再建立一张表 new,为其建立六个属性,分别是:

id 主键
title 文章标题
description 摘要
date 文章发表时间
newUrl 文章链接
imageUrl 图片链接

创建new表的SQL语句如下

CREATE TABLE `new` (
`id` int(11) NOT NULL,
`title` text NOT NULL,
`description` text NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`newUrl` text NOT NULL,
`imageUrl` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

new表插入数据

这里写图片描述

手机端的工作就是来读取数据并显示出来,不过手机端也无法直接访问数据库内容。所以在数据库端需要利用PHP将数据库内容返回为JSON格式的数据,然后手机端再去解析JSON数组

首先是进行数据库连接
mysql_connect.php


//数据库的用户名为root,密码为空
$con = mysql_connect("localhost", "root", "");
//设置字符集为utf8
mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET CHARACTER_SET_RESULT=utf8");

if (!$con){
die(mysql_error());
}
//访问数据库news
mysql_select_db("news", $con);
?>

接下来是将读取到的数据库内容返回为JSON数组
getNewsJSON.php


/*
* 获得JSON数据
*/

require 'mysql_connect.php';
$n = 0;
$result = mysql_query("select * from new");
while ($row = mysql_fetch_array($result)){
$arr[$n++] = array("title" => $row['title'],
"description" => $row['description'],
"date" => $row['date'],
"newUrl" => $row['newUrl'],
"imageUrl" => $row['imageUrl']
);
}
//数组转换为JSON字符串
echo json_encode($arr);
?>

将两个php文件放到XAMPP安装目录的htdocs文件夹下,直接存放或者再新建个文件夹存放也可以,例如我的存放路径就是:C:\xampp\htdocs\news

然后打开浏览器,输入http://localhost/news/getNewsJSON.php
如果是呈现如下格式的数据,那就说明数据库数据读取成功了。没有直接呈现中文字符是因为编码问题,无需理会。

这里写图片描述

服务器端开发完毕了,接下来就要进行移动端的设计了。

新建个工程。要做的是一个新闻客户端,新闻列表就采用RecyclerView来呈现,将默认布局改为:


<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"
tools:context="com.zy.news.MainActivity">


<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent">
android.support.v7.widget.RecyclerView>

RelativeLayout>

列表的子项布局:
new_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#f7f9fa"
android:orientation="horizontal"
android:padding="6dp">


<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/new_image"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_gravity="center" />


<LinearLayout
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_weight="1"
android:orientation="vertical"
android:padding="6dp">


<TextView
android:id="@+id/new_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@android:color/black"
android:textSize="20sp"
android:textStyle="bold" />


<TextView
android:id="@+id/new_introduction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="4"
android:textColor="@android:color/black"
android:textSize="16sp" />


<TextView
android:id="@+id/new_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="6dp"
android:textColor="@android:color/black"
android:textSize="13sp" />

LinearLayout>
LinearLayout>

SimpleDraweeView是Fresco推出的一款图片加载控件,导入SimpleDraweeView的方法是在build.gradle文件下加入语句compile 'com.facebook.fresco:fresco:0.10.0',然后点击同步即可

这里写图片描述

前边在建表时时设立了六个属性,除去主键id外,一篇新闻还有五个属性。为新闻建立一个实体NewIntroduction.java,省略相应的get和set属性。

public class NewIntroduction {
//文章标题
private String title;
//文章摘要
private String description;
//文章发表时间
private String date;
//文章链接
private String newUrl;
//图片链接
private String imageUrl;
}

新建一个NewsItemListAdapter.java文件,继承自RecyclerView.Adapter,作为RecyclerView的适配器

/**
* Created by ZY on 2016/6/10.
*/

public class NewsItemListAdapter extends RecyclerView.Adapter {

private List introductionList;

private LayoutInflater inflater;

public NewsItemListAdapter(Context context, List introductionList) {
this.introductiOnList= introductionList;
this.inflater = LayoutInflater.from(context);
}

@Override
public NewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.new_item, parent, false);
return new NewsHolder(view);
}

@Override
public void onBindViewHolder(NewsHolder holder, int position) {
holder.new_image.setImageURI(Uri.parse(introductionList.get(position).getImageUrl()));
holder.new_title.setText(introductionList.get(position).getTitle());
holder.new_introduction.setText(introductionList.get(position).getDescription());
holder.new_date.setText(introductionList.get(position).getDate());
}

@Override
public int getItemCount() {
if (introductiOnList== null || introductionList.size() == 0) {
return 0;
}
return introductionList.size();
}
}

NewsHolder也是一个自定义类,继承自RecyclerView.ViewHolder

/**
* Created by ZY on 2016/6/10.
*/

public class NewsHolder extends RecyclerView.ViewHolder {

public SimpleDraweeView new_image;

public TextView new_title;

public TextView new_introduction;

public TextView new_date;

public NewsHolder(View itemView) {
super(itemView);
new_image = (SimpleDraweeView) itemView.findViewById(R.id.new_image);
new_title = (TextView) itemView.findViewById(R.id.new_title);
new_introduction = (TextView) itemView.findViewById(R.id.new_introduction);
new_date = (TextView) itemView.findViewById(R.id.new_date);
}

}

修改MainActivity

public class MainActivity extends AppCompatActivity {

private List newIntroductionList;

private NewsItemListAdapter adapter;

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

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycleView);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));

newIntroductiOnList= new ArrayList<>();
adapter = new NewsItemListAdapter(MainActivity.this, newIntroductionList);
recyclerView.setAdapter(adapter);
}
}

此时newIntroductionList 内还没有填充数据,程序打开后还是一片空白,所以接下来就要来获取本地服务器内的数据

新建一个Util类
getNewsJSon(String strUrl)方法用来访问getNewsJSON.php页面,获取页面数据

public static String getNewsJSon(String strUrl) throws IOException {
URL url;
URLConnection urlConnection;
HttpURLConnection httpURLConnection;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
StringBuffer resultBuffer = null;
try {
url = new URL(strUrl);
urlCOnnection= url.openConnection();
httpURLCOnnection= (HttpURLConnection) urlConnection;
httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
reader = new BufferedReader(inputStreamReader);
resultBuffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
resultBuffer.append(line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (inputStream != null) {
inputStream.close();
}
}
if (resultBuffer == null) {
return null;
}
return resultBuffer.toString();
}

getNewIntroductionList(String strUrl)方法用来解析JSON数组

public static List<NewIntroduction> getNewIntroductionList(String strUrl) throws IOException {
String html = getNewsJSon(strUrl);
if (html == null) {
return null;
}
List<NewIntroduction> newIntroductionList = new ArrayList<>();
try {
JSONArray jsonArray = new JSONArray(html);

for (int i = 0; i < jsonArray.length(); i++) {
NewIntroduction newIntroduction = new NewIntroduction();
JSONObject jsonObject = jsonArray.optJSONObject(i);
String title = jsonObject.getString("title");
String description = jsonObject.getString("description");
String date = jsonObject.getString("date");
String newUrl = jsonObject.getString("newUrl");
String imageUrl = jsonObject.getString("imageUrl");

newIntroduction.setTitle(title);
newIntroduction.setDescription(description);
newIntroduction.setDate(date);
newIntroduction.setNewUrl(newUrl);
newIntroduction.setImageUrl(imageUrl);

newIntroductionList.add(newIntroduction);
}

} catch (JSONException e) {
e.printStackTrace();
}

return newIntroductionList;
}

然后在MainActivity文件中建立一个内部类MyAsyncTask继承自

AsyncTask<String, Void, List<NewIntroduction>>

用来进行联网操作。将读取到的JSON数组解析为NewIntroduction对象,传入适配器中

 class MyAsyncTask extends AsyncTask<String, Void, List<NewIntroduction>> {

@Override
protected List doInBackground(String... params) {
List newIntroductiOnList= null;
try {
newIntroductiOnList= Util.getNewIntroductionList(params[0]);
} catch (IOException e) {
e.printStackTrace();
}
return newIntroductionList;
}

@Override
protected void onPostExecute(List introductionList) {
if (introductiOnList== null || introductionList.size() == 0) {
return;
}
MainActivity.this.newIntroductionList.addAll(introductionList);
MainActivity.this.adapter.notifyDataSetChanged();
}
}

然后在onCreate(Bundle savedInstanceState)方法的最后一行new一个MyAsyncTask对象即可。模拟器访问本地服务器的IP地址为10.0.2.2,所以完整的访问地址应为http://10.0.2.2/news/getNewsJSON.php

new MyAsyncTask().execute("http://10.0.2.2/news/getNewsJSON.php");

最后还要加上联网访问权限

<uses-permission android:name="android.permission.INTERNET" />

程序运行结果如下:

这里写图片描述

代码下载地址:一个简单的联网新闻客户端的开发思路


推荐阅读
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
author-avatar
华福-日语人才_601
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有