如何降低我的应用程序的内存使用量?

时间:2014-11-08 14:11:10

标签: android memory-management

我创建了一个应用程序,用于从我服务器上的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。

我的问题是,是否有更有效和更友好的方式来实现这一目标?这是我的第一款具有动态内容的应用。

1 个答案:

答案 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)限制数据使用

您无需一次下载所有作业。下载十,当用户到达列表末尾时,允许他下载另外十个。但是这个话题超出了这个帖子。