本文使用简单的Tomcat服务器,配置方法参考博文:
https://blog.csdn.net/qq_40881680/article/details/83582484#Tomcat
注意:
(1)安装JRE或者JDK,并在系统环境变量中加入JDK_HOME变量D:\Java\jdk1.8.0_231
(2)服务器启动,报错等详见该博文
安装后的效果:
cmd
Tomcat
打开本地服务器网页:localhost:8080
内容准备:将提前准备的图片和xml文件放置在webapps的root根目录下
安卓手机将要访问该news.xml文件,并根据该xml文件进行解析;获取图片地址,展示信息和图片,端口默认使用8080
电脑的IP通过cmd ipconfig查看:
包含文件头(声明)、根节点、节点、内容、命名空间等内容
命名空间示意
<channel>
<item>
<title>军报评徐才厚title>
<description>人死账不消反腐步不停,支持,威武,顶,有希望了。description>
<image>http://192.168.1.127:8080/img/a.jpgimage>
<type>1type>
<comment>163comment>
item>
<item>
<title>女司机翻车后直奔麻将室title>
<description>女司机翻车后直奔麻将室,称大难不死手气必红description>
<image>http://192.168.1.127:8080/img/b.jpgimage>
<type>2type>
item>
<item>
<title>小伙当“男公关”以为陪美女title>
<description>来源:中国青年网,小伙当“男公关”以为陪美女,上工后被大妈吓怕description>
<image>http://192.168.1.127:8080/img/c.jpgimage>
<type>3type>
item>
<item>
<title>男子看上女孩背影xxxxtitle>
<description>来源:新京报,看到正脸后很惊喜description>
<image>http://192.168.1.127:8080/img/d.jpgimage>
<type>1type>
<comment>763comment>
item>
channel>
ListView是可以垂直滚动的列表,可以展示多个条目
View的宽高属性使用:包裹内容;展示多个条目时无法自动计算应展示的条目数,安卓系统自动多次校验,效率降低
此处就是需要将item的布局文件转换为View对象,采用View.inflate方法
控制网络收发数据:
URL url=new URL("https://www.baidu.com");
// 创建httpurlconnection对象
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int code =conn.getResponseCode();
if (code==200){
// 获取服务器返回的数据
InputStream in=conn.getInputStream();
// 把流装换为字符串,抽出为工具类
String content =StreamTools.readStream(in);
tv_result.setText(content);
}
} catch (Exception e) {
e.printStackTrace();
}
在实验过程中,在主线程里进行网络连接,报错:
android.os.NetworkOnMainThreadException
书写按钮点击事件
在子线程中更新UI:会报错:
W/System.err:> android.view.ViewRootImpl$CalledFromWrongThreadException:
网络连接
public class MainActivity extends AppCompatActivity {
protected static final int REQUESTSUCCESS=0;
protected static final int REQUESTNOTFOUND=1;
protected static final int REQUESTEXCEPTION=2;
private EditText et_path;
private TextView tv_result;
private Handler handler =new Handler(){
//这个方法在主线程中执行
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case REQUESTSUCCESS:
String content=(String) msg.obj;
tv_result.setText(content);
break;
case REQUESTNOTFOUND:
Toast.makeText(getApplicationContext(),"资源不存在",Toast.LENGTH_LONG).show();
break;
case REQUESTEXCEPTION:
Toast.makeText(getApplicationContext(),"请求异常",Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_path =findViewById(R.id.et_path);
tv_result =findViewById(R.id.tv_result);
}
public void myclick(View V){
//创建子线程,在子线程中进行联网操作
new Thread(){
@Override
public void run() {
try {
String path=et_path.getText().toString().trim();
URL url=new URL("Https://"+path);
// 创建httpurlconnection对象
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int code =conn.getResponseCode();
if (code==200){
// 获取服务器返回的数据
InputStream in=conn.getInputStream();
// 把流装换为字符串,抽出为工具类
String content =StreamTools.readStream(in);
// tv_result.setText(content);
// 更新UI的操作,使用Hander实现
Message msg=Message.abtain();//可以减少对象的创建
msg.what=REQUESTSUCCESS;
msg.obj=content;
handler.sendMessage(msg);
}
else{
// 请求不成功
Message msg=Message.abtain();//可以减少对象的创建
msg.what=REQUESTSUCCESS;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
Message msg=Message.abtain();//可以减少对象的创建
msg.what=REQUESTEXCEPTION;
handler.sendMessage(msg);
}
}
}.start();
}
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
System.out.println("nihao");
}
},5000);
java中Timer可实现类似的功能(app退出后需要销毁Timer调度)
Timer timer=new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hahhhahah");
}
}, 5000,);
但是Timer子线程中无法更新UI,但是Handler的postDelayed方法可以
File file=new File(getCacheDir(), Base64.encodeToString(path.getBytes(),Base64.URL_SAFE));
InputStream in =conn.getInputStream();
//缓存数据
FileOutputStream fos=new FileOutputStream(file);
int len=-1;
byte[] buffer=new byte[1024];//1kb
while((len=in.read(buffer))!=-1){
fos.write(buffer,0,len);
}
fos.close();
public class MainActivity extends AppCompatActivity {
private TextView et_path;
private ImageView iv;
private Handler handler=new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
iv.setImageBitmap((Bitmap)msg.obj);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_path=(TextView) findViewById(R.id.et_path);
iv=(ImageView) findViewById(R.id.iv);
}
public void myclick(View v){
new Thread(){
@Override
public void run() {
try {
String path=et_path.getText().toString().trim();
File file=new File(getCacheDir(), Base64.encodeToString(path.getBytes(),Base64.URL_SAFE));
if (file.exists() && file.length()>0){
// 如果文件存在,使用缓存数据
Bitmap bitmap= BitmapFactory.decodeFile(file.getAbsolutePath());
Message msg=Message.obtain();
msg.obj=bitmap;
handler.sendMessage(msg);
}
else{
// 如果文件不存在,则连接网络
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int code=conn.getResponseCode();
//获取图片数据,
if (code==200){
InputStream in =conn.getInputStream();
//缓存数据
FileOutputStream fos=new FileOutputStream(file);
int len=-1;
byte[] buffer=new byte[1024];//1kb
while((len=in.read(buffer))!=-1){
fos.write(buffer,0,len);
}
fos.close();
in.close();
//将输入流转换为bitmap模式,BitmapFactory从各种资源
Bitmap bitmap= BitmapFactory.decodeFile(file.getAbsolutePath());
Message msg=Message.obtain();
msg.obj=bitmap;
handler.sendMessage(msg);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
由于在子线程里处理数据,然后更新UI——是十分常见的操作,因此提供了runOnUiThread()方法;其本质还是采用handler实现
使用方法:在子线程中直接使用runOnUiThread()方法,传入一个Runnable对象
以下代码:
Bitmap bitmap= BitmapFactory.decodeFile(file.getAbsolutePath());
Message msg=Message.obtain();
msg.obj=bitmap;
handler.sendMessage(msg);
可以替换为:
final Bitmap bitmap= BitmapFactory.decodeFile(file.getAbsolutePath());
runOnUiThread(new Runnable() {
@Override
public void run() {
iv.setImageBitmap(bitmap);
}
});