我创建了一个应用程序,用于从我服务器上的XML文件中提取数据(招聘广告),并在我的应用程序中显示这些招聘广告。当我检查我的应用程序时,它使用30-50mb,我认为这对于这么简单的应用来说太多了。我尝试在一些低端设备(24mb堆大小)上运行它并且它工作正常,有点滞后但没有OOM或任何其他崩溃,所以我不认为它是内存泄漏。
我使用的初始大小为100的全局数组,加载XML文件后,数组的大小将调整为XML文件中的节点数。
全局变量
private final Integer MAX_SIZE = 100;
public String[] ID = new String[MAX_SIZE];
public String[] Category = new String[MAX_SIZE];
public String[] Title = new String[MAX_SIZE];
public String[] Content = new String[MAX_SIZE];
public String[] Link = new String[MAX_SIZE];
public Integer[] JobID = new Integer[MAX_SIZE];
public String[] nID = new String[MAX_SIZE];
public String[] nCategory = new String[MAX_SIZE];
public String[] nTitle = new String[MAX_SIZE];
public String[] nContent = new String[MAX_SIZE];
public String[] nLink = new String[MAX_SIZE];
public int[] nJobID = new int[MAX_SIZE];
public int[] nExists = new int[MAX_SIZE];
这是我用来获取XML并将条目加载到变量中的代码
private class LOADXML extends AsyncTask<String, Void, Void> {
@Override
protected void onPreExecute() {
if (swipeLayout != null) {
if (!swipeLayout.isRefreshing()) {
((MainActivity) getActivity()).load();
}
} else {
((MainActivity) getActivity()).load();
}
Arrays.fill(((MainActivity) getActivity()).jobCOUNT, 0);
}
@Override
protected Void doInBackground(String... urls) {
if (getActivity() == null) {
cancel(true);
}
if (!((MainActivity) getActivity()).fromNotif && ((MainActivity) getActivity()).refresh) {
try {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML
Document doc = parser.getDomElement(xml); // getting DOM element
Context cx = getActivity();
WriteXMLToFile(xml, cx);
NodeList nl = doc.getElementsByTagName(KEY_JOB);
listSize = 0;
SetArrayLength(nl.getLength());
// looping through all item nodes <item>
for (int i = 0; i < nl.getLength(); i++) {
if (getActivity() == null) {
cancel(true);
}
Element e = (Element) nl.item(i);
listSize += 1;
setGlobalVars(listSize - 1, parser.getValue(e, KEY_ID), parser.getValue(e, KEY_CATEGORY), parser.getValue(e, KEY_TITLE), parser.getValue(e, KEY_CONTENT), parser.getValue(e, KEY_LINK), parser.getValue(e, KEY_JOBID));
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
Activity activity = getActivity();
if (activity != null && !isCancelled()) {
((MainActivity) getActivity()).unload();
((MainActivity) getActivity()).refresh = false;
updateCountVar();
updateList();
if (swipeLayout.isRefreshing()) {
LinearLayout container = (LinearLayout) vw.findViewById(frag_container);
container.removeAllViews();
if (swipeLayout != null) {
swipeLayout.setRefreshing(false);
isRefreshing = false;
}
showJobBox(li, vw);
} else {
showJobBox(li, vw);
}
}
}
}
这是代码的一部分,负责用数据填充片段
listSize = ((MainActivity) getActivity()).nID.length;
for (Integer i = 0; i < listSize; i++) {
if (filterEntry(i) && (Integer.valueOf(((MainActivity) getActivity()).nJobID[i]) != null)) {
// Layout params
@SuppressLint("InflateParams") View item_layout = inflater.inflate(R.layout.job_box, null, false);
LinearLayout container = (LinearLayout) view.findViewById(frag_container);
TextView category = (TextView) item_layout.findViewById(R.id.jobBox_category);
TextView title = (TextView) item_layout.findViewById(R.id.jobBox_title);
TextView description = (TextView) item_layout.findViewById(R.id.jobBox_description);
TextView jobBtn = (TextView) item_layout.findViewById(R.id.jobBox_button);
TextView jobIDbox = (TextView) item_layout.findViewById(R.id.jobIDbox);
ImageButton imgBtn = (ImageButton) item_layout.findViewById(R.id.imageButton);
TextView newLabel = (TextView) item_layout.findViewById(R.id.jobBox_new);
Integer nExistsInteger = ((MainActivity) getActivity()).nExists[i];
if (nExistsInteger == 0) {
newLabel.setVisibility(View.VISIBLE);
}
// ##############################################
int id = i + 10000;
item_layout.setId(id);
category.setText(((MainActivity) getActivity()).nCategory[i]);
title.setText(((MainActivity) getActivity()).nTitle[i]);
description.setText(((MainActivity) getActivity()).nContent[i]);
Integer ido = ((MainActivity) getActivity()).nJobID[i];
jobIDbox.setText("Šifra oglasa: " + String.valueOf(ido));
final Integer a = i;
jobBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String url = ((MainActivity) getActivity()).Link[a];
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
i.setData(Uri.parse(url));
startActivity(i);
}
});
imgBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Studentski posao");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, ((MainActivity) getActivity()).nTitle[a]
+ " - " + ((MainActivity) getActivity()).nLink[a]
+ " (Via http://bit.ly/StudentServis)");
startActivity(Intent.createChooser(sharingIntent, "Podijeli koristeći"));
}
});
RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (i > 0) {
params1.addRule(RelativeLayout.ALIGN_BOTTOM, id - 1);
item_layout.setLayoutParams(params1);
} else {
item_layout.setPadding(10, 10, 10, 10);
}
container.addView(item_layout);
if (i == listSize - 1) {
@SuppressLint("InflateParams") View item_layout_dummy = inflater.inflate(R.layout.dummy, null);
container.addView(item_layout_dummy);
}
((MainActivity) getActivity()).ID[i] = ((MainActivity) getActivity()).nID[i];
((MainActivity) getActivity()).Category[i] = ((MainActivity) getActivity()).nCategory[i];
((MainActivity) getActivity()).Title[i] = ((MainActivity) getActivity()).nTitle[i];
((MainActivity) getActivity()).Content[i] = ((MainActivity) getActivity()).nContent[i];
((MainActivity) getActivity()).Link[i] = ((MainActivity) getActivity()).nLink[i];
((MainActivity) getActivity()).JobID[i] = ((MainActivity) getActivity()).nJobID[i];
}
}
我确保在切换片段(到另一个类别)时,如果已加载数据,则跳过LOADXML doInBackground。
我的问题是,是否有更有效和更友好的方式来实现这一目标?这是我的第一款具有动态内容的应用。
答案 0 :(得分:2)
阶段1)使用对象。
沟渠阵列。你使用它们的方式是无效的,系统可以为你做很多工作。你将至少使用一半的内存。
在您的活动中,而不是众多阵列(也是重复的)只有一个列表:
private ArrayList<Job> jobs = new ArrayList<Job>();
随之为它创建一个Holder模式类。
public static class Job {
public int jobId;
public String id, category, title, content, link;
public boolean exists;
}
以上内容可以帮助您避免使用多个阵列无效地管理数据。
现在重写XML加载任务,将所有作业加载到后台列表中。只有在完成后才开始更新视图。
私有类LoadXml扩展了AsyncTask&gt; {
@Override
protected void onPreExecute() {
//
}
@Override
protected List<Job> doInBackground(String... urls) {
try {
final List<Job> jobs = new ArrayList<Job>();
// this method is written in pseudo code as I don't know anything about parsing XML
// assume one url containing all jobs
String xml = getXmlFromUrl(urls[0]);
// loop through each Job element
for(Element e : doc) {
// create a new Job instance
Job job = new Job();
// load the Job data
job.id = e.getAttribute("id");
// etc.
// add the Job to the list
jobs.add(job);
}
// return Job list
return jobs;
} catch (Exception ex) {
ex.printStackTrace();
// if anything fails, return null to indicate
return null;
}
}
@Override
protected void onPostExecute(List<Job> result) {
// send the list to activity and let it handle it
((MainActivity)getActivity()).updateJobList(result);
// MainActivity.updateJobList() will contain pretty much what was here.
}
}
阶段2)限制数据使用
您无需一次下载所有作业。下载十,当用户到达列表末尾时,允许他下载另外十个。但是这个话题超出了这个帖子。