2

これは、stackoverflow に関する私の最初の投稿であり、Android は初めてです。フォーラムで同様の質問を検索したところ、SAX parser progress monitoringという質問が見つかりました。しかし、残念ながらそれは私を助けません。私のアプリはカレンダーにイベントを登録する必要があります。私が達成した最初のことは、xml ファイルのダウンロードを進めることでした。これは、添付のコードで確認できます。その後、progressDialog をリセットして、解析の進行状況の追跡を開始します。これが新しい setMessage() とパーセンテージ値で実行できれば素晴らしいでしょう。解析後、データを使用してカレンダーにイベントを登録します。これも同じ progressDialog で行われます。

しかし、最初に、解析の進行状況を追跡する方法を知りたいです。何かアイデアがあれば最高です。ありがとうございました

public class AddCoursesToCalendar extends Activity {

public static final int progress_bar_type = 0; 
ArrayList<String> selectedCourses;
public ProgressDialog progressDialog;

@Override
public void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    setContentView(R.layout.activity_add_courses_to_calendar);
    if (bundle != null) {
        selectedCourses = bundle.getStringArrayList("selectedCourses");
    }
    new GetDataTask().execute();
}

private Boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo ni = cm.getActiveNetworkInfo();
    if (ni != null && ni.isConnected())
        return true;

    return false;
}

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
    case progress_bar_type: 
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Downloading file. Please wait...");
        progressDialog.setIndeterminate(false);
        progressDialog.setMax(100);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setCancelable(true);
        progressDialog.show();
        return progressDialog;
    default:
        return null;
    }
}

public class GetDataTask extends AsyncTask<String, String, Integer> {

    private static final String URL = "http://10.0.2.2/WIN2.xml";
    private static final String KEY_ITEM = "Item"; 
    private static final String KEY_DAUER = "Duration"; 
    private static final String KEY_ENDE = "End";
    private static final String KEY_SEMESTER_DOZENT = "Location";
    private static final String KEY_RAUMMITSTOCKWERK = "Organizer"; 
    private static final String KEY_START = "Start";
    private static final String KEY_VERANSTALTUNGSNAME = "Subject";

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        onCreateDialog(progress_bar_type);
    }


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

        if (isOnline()) {
            XMLParser parser = new XMLParser();
            String xml = parser.getXmlFromUrl(URL, this);
            long id = 0;

            Document doc = parser.getDomElement(xml, this);

            NodeList nl = doc.getElementsByTagName(KEY_ITEM);

            for (int i = 0; i < nl.getLength(); i++){
                Element e = (Element) nl.item(i);

                for (String s : selectedCourses) {
                    if (parser.getValue(e, KEY_VERANSTALTUNGSNAME)
                            .contains(s)) {

                        String dozent = null;
                        int spaceIndex = parser.getValue(e,
                                KEY_SEMESTER_DOZENT).indexOf(" ");
                        int lastIndex = parser.getValue(e,
                                KEY_SEMESTER_DOZENT).length();
                        if (spaceIndex != -1) {
                            dozent = parser
                                    .getValue(e, KEY_SEMESTER_DOZENT)
                                    .substring(spaceIndex, lastIndex);
                        }

                        addEvent(
                                parser.getValue(e, KEY_VERANSTALTUNGSNAME),
                                parser.getValue(e, KEY_START),
                                parser.getValue(e, KEY_ENDE),
                                parser.getValue(e, KEY_DAUER),
                                dozent,
                                parser.getValue(e, KEY_RAUMMITSTOCKWERK),
                                id);

                    } id++;
                }
            }
        } else {
            Toast.makeText(AddCoursesToCalendar.this, "No Connection..",
                    Toast.LENGTH_LONG).show();
        }
        return 1;
    }

      public void doProgress(String value){
            publishProgress(value);
        }


    @Override
    protected void onPostExecute(Integer result) {
        progressDialog.dismiss();
        super.onPostExecute(result);
    }

    protected void onProgressUpdate(String... progress) {
        progressDialog.setProgress(Integer.parseInt(progress[0]));
   }

    protected void addEvent(String title, String start, String end,
            String duration, String organizer, String location, long id) {

        SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
        long startInMillis = 0, endInMillis = 0;
        Date startDate, endDate;
        try {
            startDate = format.parse(start);
            endDate = format.parse(end);
            startInMillis = startDate.getTime();
            endInMillis = endDate.getTime();
        } catch (ParseException e1) {
            e1.printStackTrace();
        }

        TimeZone timeZone = TimeZone.getDefault();
        ContentResolver cr = getContentResolver();
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone.getID());
        values.put(CalendarContract.Events.DTSTART, startInMillis);
        values.put(CalendarContract.Events.DTEND, endInMillis);
        values.put(CalendarContract.Events.TITLE, title);
        values.put(CalendarContract.Events.EVENT_LOCATION, "Location: " + location);
        values.put(CalendarContract.Events.CALENDAR_ID, 1);
        Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
        ContentUris.withAppendedId(uri, id);
    }

}

}

そして、ダウンロードと解析を担当するクラスは次のとおりです。

public class XMLParser {

public String getXmlFromUrl(String url, AddCoursesToCalendar.GetDataTask task) {
    String xml = null;

    try {
        int count;
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        HttpResponse httpResponse = httpClient.execute(httpPost);

        HttpEntity httpEntity = httpResponse.getEntity();
        long lenghtOfFile = httpEntity.getContentLength();

        byte data[] = new byte[1024];
        long total = 0;
        while ((count = httpEntity.getContent().read(data)) != -1) {
            total += count;
          task.doProgress(""+(int)((total*100)/lenghtOfFile));
        }

        xml = EntityUtils.toString(httpEntity, "UTF-8");

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

public Document getDomElement(String xml, AddCoursesToCalendar.GetDataTask task) {
    Document doc = null;
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {

        DocumentBuilder db = dbf.newDocumentBuilder();
        InputSource is = new InputSource();
        StringReader reader = new StringReader(xml);
        is.setCharacterStream(reader);
        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;
}

public String getValue(Element item, String str) {
    NodeList n = item.getElementsByTagName(str);
    return this.getElementValue(n.item(0));
}

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

}

最初の投稿のスタイルがよかったといいのですが、そうでない場合は教えてください。前もって感謝します

4

1 に答える 1

0

XML は非常に大きく、解析には少なくとも30 秒かかると想定しています。それ以外の場合は、不確定なインジケーターを表示してください;)

また、コードを簡素化するためURL.openStream()に、フル機能の の代わりに使用HttpClientし、単純なものに切り替えるGETこともできます (パラメーターを送信しないため、サーバーで が必要な理由がわかりませんPOST)。

ファイルが非常に大きい場合 (もちろん電話用)、メモリ使用量を考慮する必要があり、DOM からSAX インターフェースに切り替えて XML を処理します。SAX は、ストリームのスキャン中にイベント ベースのインターフェイスを提供するため、処理を開始する前にファイル全体をメモリにロードする必要はありません。これは大きなファイルであり、メモリ不足になりたくないことを忘れないでください。

SAX を使用すると、ダウンロード中にファイルを解析できるため、合計時間と残り時間を計算する際にネットワーク遅延を無視できます。この時点で、進行状況はcurrent item / totalで概算できます。内部カウンターを更新して現在のアイテムを追跡することはできますが、問題は合計を計算する方法です。の観点から考えることができます。

  1. バイト (例processed 12932/2791290 Bytes)
  2. ビジネスアイテム (例processed 80/291 Items)

どちらの場合も、サーバーからのサポートが必要です。Content-LengthHTTP ヘッダーまたはプリアンブル (<manifest>このスニペットで呼び出されます)を提供する必要があります。

<root>
  <manifest>
    <total>291</total>
  </manifest>
  ...
  <item id="foobar1">
    <foo>Foo</foo>
    <bar>Bar</bar>
  </item>
  ...
</root>

このAsyncTask部分は非常に簡単です。publishProgress()内で使用でき、UI スレッドでdoInBackground()呼び出されます。onProgressUpdate()このメソッド内で、ダイアログの進行状況を更新します。

最後にいくつか注意事項があります。画面が回転すると (既定の構成が想定されます)、アクティビティは破棄されてから再作成されます。経由で表示されるダイアログActivity.showDialogはシステムによって自動的に再作成されますが、古いものAsyncTaskは実行され続け、古い (現在は破棄されているがガベージ コレクションはされていない) アクティビティと古いダイアログへの参照が保持される場合があることに注意してください。これには自分で取り組む必要があります。代替手段が多すぎます(ローダー フレームワークを含む)。

タスクが思ったほど単純ではないことを理解していただければ幸いです。私のアドバイスは、ビジネス要件を慎重に検討し、最も単純で堅牢なソリューションを考え出すことです。結局のところ、XML をダウンロードして進行状況ダイアログを表示することは、アプリの主なタスク ;)

于 2012-10-24T14:03:21.187 に答える