2014-11-08 4 views
1

서버의 XML 파일에서 데이터 (작업 광고)를 가져와 내 애플리케이션에 해당 작업 광고를 표시하는 앱을 만들었습니다. 내 앱을 확인했을 때, 30 ~ 50MB를 사용하고 있었는데, 그렇게 간단한 앱에 너무 많이 있다고 생각한다. 내가 어떤 낮은 엔드 장치 (24 메가 바이트 힙 크기)에서 실행을 시도하고 괜찮아, 약간의 laggy하지만 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]; 

이 내가 변수

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); 
       } 
      } 
     } 
    } 

에 XML로드 항목을 가져 오기 위해 사용하는 코드이며,이 조각을 채우는 담당하는 코드의 일부입니다 데이터 있음

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]; 
       } 
      } 

나는 조각이 전환 될 때 (diffe rent 카테고리), 데이터가 이미로드 된 경우 LOADXML doInBackground를 건너 뜁니다.

제 질문은이 목표를 달성하기위한보다 효율적이고 메모리가 더 좋은 방법입니까? 이것은 동적 인 내용을 가진 나의 첫 번째 앱입니다.

답변

2

1 단계) 개체를 사용하십시오.

도랑 배열. 당신이 그들을 사용하는 방법은 효과가 없다, 시스템은 당신을 위해 많은 일을 할 수 있습니다. 사용 된 메모리의 절반 이상을 사용하게됩니다. 그것은 당신의 작업을위한 홀더 패턴 클래스를 만들와 함께

private ArrayList<Job> jobs = new ArrayList<Job>(); 

: 대신 (또한 중복) 다양한 배열의 활동에

은 하나 개의 목록이있다.

public static class Job { 
    public int jobId; 
    public String id, category, title, content, link; 
    public boolean exists; 
} 

위와 같이 설정하면 여러 어레이를 사용하여 데이터를 효과적으로 관리하지 않아도됩니다.

이제 XML 로딩 작업을 다시 작성하여 모든 작업을 백그라운드의 목록에로드하십시오. 끝나면보기를 업데이트하기 시작합니다.

개인 클래스 LoadXml은 AsyncTask를 확장> {

@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 단계) 데이터 사용량을 제한

당신은 한 번에 모든 작업을 다운로드 할 필요가 없습니다. 다운로드 10, 사용자가 목록의 끝에 도달하면 다른 10을 다운로드 할 수 있습니다. 그러나 그 주제는이 게시물을 넘어선 것입니다.

+0

감사합니다. 지금은 잘 작동하고 있습니다. 차이는별로 없지만 이전보다 좀 더 빠르고 반응이 좋았습니다. 적어도 나를 위해이 방법을 이해하는 것이 더 쉽습니다. –

관련 문제