0

我正在开发一个项目,该项目向 Web 服务器发布请求,并且 Web 服务器以 XML 格式响应。这是真正的故事开始。实际上,我在同一活动中向 Web 服务器发送请求并在同一活动中获得响应,响应包含分辨率为 500X800 的图像和一些纯文本。

public class Home extends Activity implements AdapterView.OnItemClickListener {
    /** Called when the activity is first created. */

    Context context = Home.this;
    ArrayList<String> BookTitle = new ArrayList<String>();
    ArrayList<String> BookCoverPhotos = new ArrayList<String>();
    ArrayList<String> BookAuther = new ArrayList<String>();
    ArrayList<String> BookPublishDate = new ArrayList<String>();

    URL bookImageURL = null;
    Bitmap bitMapImage = null;

    View homeTabLayout;
    View reviewLayout;
    ImageButton btnBack;

    // All static variables
    static final String URL = "http://www.shiaislamiclibrary.com/requesthandler.ashx";
    // XML node keys
    static final String KEY_ITEM = "Book"; // parent node
    static final String KEY_BOOKAUTHOR = "BookAuthor";
    static final String KEY_BOOKDATEPUBLISHED = "DatePublished";
    static final String KEY_BOOKTITLE = "BookTitle";
    static final String KEY_BOOKCODE = "BookCode";
    static final String KEY_BOOKIMAGE = "BookImage";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.home_activity);

        // Get XML Data in a Array List

        XMLParser parser = new XMLParser();
        String xml = parser.getXmlFromUrl(URL, "Imam Ali"); // getting
                                                            // XML
        Log.i("XML FORMAT", xml);
        Document doc = parser.getDomElement(xml); // getting DOM element

        NodeList nl = doc.getElementsByTagName(KEY_ITEM);

        // looping through all item nodes <item>
        for (int i = 0; i < nl.getLength(); i++) {
            Element e = (Element) nl.item(i);

            BookTitle.add(parser.getValue(e, KEY_BOOKTITLE));
            BookCoverPhotos.add("http://shiaislamicbooks.com/books_Snaps/"
                    + parser.getValue(e, KEY_BOOKCODE) + "/1.jpg");
            BookAuther.add(parser.getValue(e, KEY_BOOKAUTHOR));
            BookPublishDate.add(parser.getValue(e, KEY_BOOKDATEPUBLISHED));
            Log.i("URLs", BookPublishDate + "::" + BookAuther + "::"
                    + BookTitle + BookCoverPhotos.toString());

        }

        // OverView Page Views...

        final ImageView imgOverVuBookCoverPhoto = (ImageView) findViewById(R.id.img_OverVuBookCoverPhoto);
        final TextView txtOverVuBookTitle = (TextView) findViewById(R.id.txt_revwBookTitle);
        final TextView txtOverVuBookAuthor = (TextView) findViewById(R.id.txt_revwAutherName);
        final TextView txtBookPublishDate = (TextView) findViewById(R.id.txt_PublishDate);

        homeTabLayout = findViewById(R.id.rel_HomeLayout);
        reviewLayout = findViewById(R.id.scroll_ReviewLayout);
        reviewLayout.setVisibility(View.GONE);

        btnBack = (ImageButton) findViewById(R.id.btnBack);
        btnBack.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                reviewLayout.setVisibility(View.GONE);
                homeTabLayout.setVisibility(View.VISIBLE);

            }
        });

        final GridView gridView = (GridView) findViewById(R.id.gridview);
        gridView.setAdapter(new ImageAdapter(this));
        gridView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int pos,
                    long arg3) {

                reviewLayout.setVisibility(View.VISIBLE);
                homeTabLayout.setVisibility(View.GONE);

                Toast.makeText(context, BookTitle.get(pos), Toast.LENGTH_SHORT)
                        .show();

                txtOverVuBookTitle.setText(BookTitle.get(pos));
                txtOverVuBookAuthor.setText(BookAuther.get(pos));
                txtBookPublishDate.setText(BookPublishDate.get(pos));

                try {
                    bookImageURL = new URL(BookCoverPhotos.get(pos));
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    Toast.makeText(context, "Network Error", Toast.LENGTH_LONG)
                            .show();
                    Log.i("URL", "ERROR");
                }

                try {
                    bitMapImage = BitmapFactory.decodeStream(bookImageURL
                            .openConnection().getInputStream());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Toast.makeText(context, "Bitmap Error", Toast.LENGTH_LONG)
                            .show();
                    Log.i("BITMAP", "ERROR");
                }

                imgOverVuBookCoverPhoto.setImageBitmap(bitMapImage);
            }
        });

    }

    public class ImageAdapter extends BaseAdapter {
        private Context context;

        public ImageAdapter(Context c) {
            context = c;
        }

        // ---returns the number of images---
        public int getCount() {
            // return imageIDs.length;
            return BookCoverPhotos.size();
            // return 6;
        }

        // ---returns the ID of an item---
        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        // ---returns an ImageView view---
        public View getView(int position, View convertView, ViewGroup parent) {

            // ImageView bmImage;

            ImageView img_BookCoverPhoto;
            img_BookCoverPhoto = new ImageView(context);

            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            View row = inflater.inflate(R.layout.grid_style, parent, false);

            TextView txt_BooksTitle = (TextView) row
                    .findViewById(R.id.txt_BookTitle);
            txt_BooksTitle.setText(BookTitle.get(position) + "");

            img_BookCoverPhoto = (ImageView) row
                    .findViewById(R.id.imgBookCover);

            try {
                bookImageURL = new URL(BookCoverPhotos.get(position));
            } catch (MalformedURLException e) {
                e.printStackTrace();
                Toast.makeText(context, "Network Error", Toast.LENGTH_LONG)
                        .show();
                Log.i("URL", "ERROR");
            }

            try {
                bitMapImage = BitmapFactory.decodeStream(bookImageURL
                        .openConnection().getInputStream());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Toast.makeText(context, "Bitmap Error", Toast.LENGTH_LONG)
                        .show();
                Log.i("BITMAP", "ERROR");
            }
            // img_BookCoverPhoto.setImageResource(imageIDs[position]);
            img_BookCoverPhoto.setImageBitmap(bitMapImage);

            return row;
        }

    }

    public class AsyncTaskForUI extends AsyncTask<String, Integer, String> {
        ProgressDialog progressDialog;

        @Override
        protected void onPreExecute() {

            super.onPreExecute();
            progressDialog = ProgressDialog
                    .show(context,
                            "Loading...",
                            "This may take a few minuts\nDepending Upon your Internet Connection Speed",
                            true);

        }

        @Override
        protected String doInBackground(String... params) {

            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(String result) {

            super.onPostExecute(result);
            progressDialog.dismiss();
            Toast.makeText(context, "Completed", Toast.LENGTH_SHORT).show();
        }

    }

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

    }
}

我在包含 ImageView 和 textView 的自定义 GridView 中加载图像和文本。这是布局的XML

    <LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget44"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/imgBookCover"
        android:layout_width="150dp"
        android:layout_height="180dp"
        android:scaleType="center"
        android:adjustViewBounds="true"
        android:src="@drawable/book1">
    </ImageView>

    <TextView
        android:id="@+id/txt_BookTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="TextView"
        android:layout_margin="5dp"
        android:textColorHighlight="#656565" 
        android:textColor="@color/White">
    </TextView>

</LinearLayout>

这也是我的 XMLParser.java 类代码

    public class XMLParser {

    // constructor
    public XMLParser() {

    }

    /**
     * Getting XML from URL making HTTP request
     * 
     * @param url
     *            string
     * */
    public String getXmlFromUrl(String url, String SearchKeywords) {
        String xml = null;

        try {
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();

            HttpPost httpPost = new HttpPost(url);

            /*ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
                    3);
            nameValuePairs.add(new BasicNameValuePair("type", "Free Books"));
            nameValuePairs.add(new BasicNameValuePair("lang", "English"));
            nameValuePairs.add(new BasicNameValuePair("book_title", "hasan"));

            try {
                httpPost.setEntity(new UrlEncodedFormEntity(
                        nameValuePairs));

            } catch (UnsupportedEncodingException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }*/

            String postParameter = "type=Free Books&lang=English&book_title="+SearchKeywords;

            try {
                httpPost.setEntity(new StringEntity(postParameter));
            }catch (Exception e) {
                // TODO: handle exception
            }


            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            xml = EntityUtils.toString(httpEntity);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // return XML
        return xml;
    }

    /**
     * Getting XML DOM element
     * 
     * @param XML
     *            string
     * */
    public Document getDomElement(String xml) {
        Document doc = null;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {

            DocumentBuilder db = dbf.newDocumentBuilder();

            InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));
            doc = db.parse(is);

        } catch (ParserConfigurationException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        } catch (SAXException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        } catch (IOException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        }

        return doc;
    }

    /**
     * Getting node value
     * 
     * @param elem
     *            element
     */
    public final String getElementValue(Node elem) {
        Node child;
        if (elem != null) {
            if (elem.hasChildNodes()) {
                for (child = elem.getFirstChild(); child != null; child = child
                        .getNextSibling()) {
                    if (child.getNodeType() == Node.TEXT_NODE) {
                        return child.getNodeValue();
                    }
                }
            }
        }
        return "";
    }

    /**
     * Getting node value
     * 
     * @param Element
     *            node
     * @param key
     *            string
     * */
    public String getValue(Element item, String str) {
        NodeList n = item.getElementsByTagName(str);
        return this.getElementValue(n.item(0));
    }
}

代码工作得很好,但是它会挂起应用程序,直到服务器发送响应并且我的应用程序显示黑屏,直到它将所有图像和文本加载到所需的视图中。当我滚动 gridView 有时它会给出异常

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
  • 但问题是现在我想在 AsyncTask 中进行 XML 解析和位图解码。如何在 AsynTask 类的单个 doInbackground() 方法中实现这两项任务。
  • 还给出了使用 AsyncTask 类将高分辨率图像调整为低分辨率的代码片段。
4

1 回答 1

0

您应该在将图像解码到内存之前检查要下载的图像的大小,这可以通过启用inJustDecodeBoundsBitmapFactory 选项来完成。之后,您可以根据要加载的所需大小缩放您的位图。我已经详细回答here了如何在将 Bitmap 加载到内存之前获取它的大小。

我创建了一个方法,它获取图像的 url、requiredHeight、requiredWidth 并返回一个缩放后适合的位图。

private static Bitmap decodeBitmapFromStream(String urlString, 
                                              int reqWidth, int reqHeight) {

        URL url = null;
            InputStream is = null;
            try {
                url = new URL(urlString);
                is = (InputStream) url.getContent();
            } catch (Exception e) {
                e.printStackTrace();
            }

            // First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(is, null, options);

            // Height and Width of downloaded Image
            int height = options.outHeight;
            int width = options.outWidth;

            // Calculate inSampleSize
            options.inSampleSize = Math.min(width/reqWidth, height/reqHeight);

       // As InputStream can be used only once we have to regenerate it again.
            try {
                is = (InputStream) url.getContent();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            return  BitmapFactory.decodeStream(is, null, options);
        }
于 2012-11-19T07:28:11.293 回答