2024年Android-搭建简单服务端+ListView异步加载数据,2024年最新百度安卓面试

写在最后

最后我想说:对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

相信它会给大家带来很多收获:

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

根据服务端list.xml,我们需要定义一个实体类:

/07_DataAsyncLoad/src/com/wwj/domain/Contact.java

package com.wwj.domain;

/**

  • 联系人实体类

  • @author wwj

*/

public class Contact {

public int id;

public String name;

public String image;

public Contact(int id, String name, String image) {

this.id = id;

this.name = name;

this.image = image;

}

public Contact() {

}

}

需要访问服务端并且解析xml文件,我们定义一个服务类:

/07_DataAsyncLoad/src/com/wwj/service/ContactService.java

package com.wwj.service;

import java.io.File;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;

import org.xmlpull.v1.XmlPullParser;

import com.wwj.domain.Contact;

import com.wwj.utils.MD5;

import android.net.Uri;

import android.util.Xml;

public class ContactService {

/**

  • 获取联系人

  • @return

*/

public static List getContacts() throws Exception{

// 服务器文件路径

String path = “http://192.192.8.233:8080/Test/list.xml”;

HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();

conn.setConnectTimeout(5000); //设置超时5秒

conn.setRequestMethod(“GET”); //设置请求方式

if(conn.getResponseCode() == 200){ //连接成功返回码200

return parseXML(conn.getInputStream());

}

return null;

}

/**

  • 利用pull解析器对xml文件进行解析

  • @param xml

  • @return

  • @throws Exception

*/

private static List parseXML(InputStream xml) throws Exception{

List contacts = new ArrayList();

Contact contact = null;

XmlPullParser pullParser = Xml.newPullParser();

pullParser.setInput(xml, “UTF-8”);

int event = pullParser.getEventType(); //取得开始文档语法

while(event != XmlPullParser.END_DOCUMENT){ //只要不等于文档结束事件,循环解析

switch (event) {

case XmlPullParser.START_TAG: //开始标签

if(“contact”.equals(pullParser.getName())){

contact = new Contact();

contact.id = new Integer(pullParser.getAttributeValue(0));

}else if(“name”.equals(pullParser.getName())){

contact.name = pullParser.nextText(); //取得后面节点的文本值

}else if(“image”.equals(pullParser.getName())){

contact.image = pullParser.getAttributeValue(0); //取得第一个属性的值

}

break;

case XmlPullParser.END_TAG: //结束标签

if(“contact”.equals(pullParser.getName())){

contacts.add(contact); //将contact对象添加到集合中

contact = null;

}

break;

}

event = pullParser.next(); //去下一个标签

}

return contacts;

}

/**

  • 获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来

  • @param path 图片路径

  • @return

*/

public static Uri getImage(String path, File cacheDir) throws Exception{// path -> MD5 ->32字符串.jpg

File localFile = new File(cacheDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf(“.”)));

if(localFile.exists()){

return Uri.fromFile(localFile);

}else{

HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();

conn.setConnectTimeout(5000);

conn.setRequestMethod(“GET”);

if(conn.getResponseCode() == 200){

FileOutputStream outStream = new FileOutputStream(localFile);

InputStream inputStream = conn.getInputStream();

byte[] buffer = new byte[1024];

int len = 0;

while( (len = inputStream.read(buffer)) != -1){

outStream.write(buffer, 0, len);

}

inputStream.close();

outStream.close();

return Uri.fromFile(localFile);

}

}

return null;

}

}

上面代码已经很清楚的定义了获取服务端数据的方法,大致流程是这样的:传递一个网络路径path,通过URL打开连接,通过HttpURLConnection连接服务端,得到输入流,解析xml文件再获得数据。

上面代码获取网络图片,需要进行MD5加密计算,具体方法如下:

/07_DataAsyncLoad/src/com/wwj/utils/MD5.java

package com.wwj.utils;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

public class MD5 {

/**

  • MD5加密算法

  • @param content

  • @return

*/

public static String getMD5(String content) {

try {

MessageDigest digest = MessageDigest.getInstance(“MD5”);

digest.update(content.getBytes());

return getHashString(digest);

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

}

return null;

}

/**

  • 获得哈希字符串

  • @param digest

  • @return

*/

private static String getHashString(MessageDigest digest) {

StringBuilder builder = new StringBuilder();

for (byte b : digest.digest()) {

builder.append(Integer.toHexString((b >> 4) & 0xf));

builder.append(Integer.toHexString(b & 0xf));

}

return builder.toString();

}

}

好,这样我们的服务类就已经写完了,这时我们在MainActivity进行异步加载数据:

/07_DataAsyncLoad/src/com/wwj/asyntask/MainActivity.java

package com.wwj.asyntask;

import java.io.File;

import java.util.List;

import com.wwj.adapter.ContactAdapter;

import com.wwj.asyntask.R;

import com.wwj.domain.Contact;

import com.wwj.service.ContactService;

import android.app.Activity;

import android.os.Bundle;

import android.os.Environment;

import android.os.Handler;

import android.os.Message;

import android.widget.ListView;

public class MainActivity extends Activity {

ListView listView;

File cache; // 缓存文件

Handler handler = new Handler() {

public void handleMessage(Message msg) {

listView.setAdapter(new ContactAdapter(MainActivity.this,

(List) msg.obj, R.layout.listview_item, cache));

}

};

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

listView = (ListView) this.findViewById(R.id.listView);

cache = new File(Environment.getExternalStorageDirectory(), “cache”); // 实例化缓存文件

if (!cache.exists())

cache.mkdirs(); // 如果文件不存在,创建

// 开一个线程来加载数据

new Thread(new Runnable() {

public void run() {

try {

List data = ContactService.getContacts();

// 通过handler来发送消息

handler.sendMessage(handler.obtainMessage(22, data));

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

}

@Override

protected void onDestroy() {

// 删除缓存

for (File file : cache.listFiles()) {

file.delete();

}

cache.delete();

super.onDestroy();

}

}

这里我们开了一个线程来加载数据,是因为网络操作不能在UI线程中进行,加载完数据后通过Hanlder发送消息,显示列表。

一般情况下,我们获取图片需要另外处理,我们有很多种方法,最常用的就是Handler+Thread和AsyncTask两种,具体实现来看:

/07_DataAsyncLoad/src/com/wwj/adapter/ContactAdapter.java

我们定义了一个列表适配器,用来填充我们的数据,我们的图片异步加载也在这里实现了:

package com.wwj.adapter;

import java.io.File;

import java.util.List;

import android.content.Context;

import android.net.Uri;

import android.os.AsyncTask;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.ImageView;

import android.widget.TextView;

import com.wwj.asyntask.R;

import com.wwj.domain.Contact;

import com.wwj.service.ContactService;

/**

  • 自定义适配器

  • @author wwj

*/

public class ContactAdapter extends BaseAdapter {

private List data; // 缓存数据

private int listviewItem; // 条目id

private File cache; // 缓存文件

LayoutInflater layoutInflater;

public ContactAdapter(Context context, List data,

int listviewItem, File cache) {

this.data = data;

this.listviewItem = listviewItem;

this.cache = cache;

layoutInflater = (LayoutInflater) context

.getSystemService(Context.LAYOUT_INFLATER_SERVICE);// 获取布局填充服务

}

/**

  • 得到数据的总数

*/

public int getCount() {

return data.size();

}

/**

  • 根据数据索引得到集合所对应的数据

*/

public Object getItem(int position) {

return data.get(position);

}

public long getItemId(int position) {

return position;

}

/**

  • 当listView每显示一个条目的时候,都会调用这个方法

*/

public View getView(int position, View convertView, ViewGroup parent) {

ImageView imageView = null;

TextView textView = null;

if (convertView == null) {

convertView = layoutInflater.inflate(listviewItem, null); // 获取条目的view对象

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。这也是我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

er.inflate(listviewItem, null); // 获取条目的view对象

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。这也是我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。

[外链图片转存中…(img-PmtZrLlQ-1714816768190)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用 ListView 异步加载图片时,可以通过以下步骤实现: 1. 创建一个自定义的适配器(Adapter)类,继承自 BaseAdapter。这个适配器将负责管理数据和视图的绑定。 2. 在适配器中,创建一个内部类 ViewHolder,用于保存列表项中的视图引用。这个类将包含一个 ImageView 用于显示图片。 3. 在适配器的 getView 方法中,获取当前列表项的数据,并更新 ViewHolder 中的 ImageView。 4. 在更新 ImageView 时,可以使用异步加载图片的第三方库,如 Glide 或 Picasso。这些库提供了简单的接口来加载网络图片,并且处理了图片的缓存和压缩等问题。 下面是一个简单的示例代码: ```java public class CustomAdapter extends BaseAdapter { private List<String> imageUrlList; private Context context; public CustomAdapter(Context context, List<String> imageUrlList) { this.context = context; this.imageUrlList = imageUrlList; } @Override public int getCount() { return imageUrlList.size(); } @Override public Object getItem(int position) { return imageUrlList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false); viewHolder = new ViewHolder(); viewHolder.imageView = convertView.findViewById(R.id.image_view); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } String imageUrl = imageUrlList.get(position); // 使用 Glide 异步加载图片 Glide.with(context) .load(imageUrl) .placeholder(R.drawable.placeholder_image) // 加载中显示的占位图 .error(R.drawable.error_image) // 加载失败显示的错误图 .into(viewHolder.imageView); return convertView; } static class ViewHolder { ImageView imageView; } } ``` 在上述示例代码中,CustomAdapter 是自定义的适配器类,其中的 getView 方法中使用了 Glide 来异步加载图片。你可以将 imageUrlList 替换为你自己的图片地址列表,并根据需要修改加载中和加载失败时显示的图片资源。同时,记得在布局文件中定义好 ImageView 的 id。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值