#android #scala
#Android #scala
Вопрос:
Я потратил на это слишком много часов и до сих пор продолжал обходиться без функции publishProgress () … к счастью, onPostExecute также выполняется в потоке пользовательского интерфейса, поэтому мне пришлось создать N потоков для каждого изображения, которое я хочу загрузить, вместо одного большого потока, который должен был обновлять listview. Итак, не фатально, но очень неприятно.
Прежде всего, большое спасибо этим страницам за предоставление более подробной информации и способов [ссылка 2!] иметь чистую реализацию Scala…
(1) http://blog.nelsonsilva.eu/2009/10/31/scala-on-android-101-proguard-xmlparser-and-function2asynctask что является обходным путем для: issues.scala-lang.org обзор SI-1459 (новые пользователи ограничены 2 ссылками)
(2) va.eu/2009/10/31/scala-on-android-101-proguard-xmlparser-and-function2asynctask что является обходным путем для: ТО ЖЕ, ЧТО И ВЫШЕ
К сожалению, ни один из них, похоже, не работал для меня на Scala 2.8.1 с Android 2.2.2 под управлением Android-x86 на Virtual box, Ubuntu 11.04.
Вот мой фактический код, мусор удален, только самое необходимое … если кто-нибудь может сказать мне, как вызвать обратный вызов, я буду очень рад, и это еще даже не Рождество. Я потратил часы на это и не могу заставить его работать вообще, я перепробовал все варианты типа «Progress», так как использование AnyRef действительно работает, но любой другой тип не работает как тип «Params», подробности об этом см. (2) выше.
Увы, я получаю preExecute (не показан), doInBackground и postExecute, но обратных вызовов выполнения публикации не видно. 🙁
Код…
private class FeedLoaderTask(val activity: ActivityFeedReader)
extends android.os.AsyncTask[AnyRef, Seq[FeedEntry], Seq[FeedEntry]]
{
/** @brief dialog to show our progress */
private var dlgBusy:ProgressDialog = null;
override def onPreExecute() {
dlgBusy = ProgressDialog.show(...)
}
override protected def doInBackground(params: AnyRef*): Seq[FeedEntry] = {
// resorted to AnyRef for reasons explained above although
val url = params.apply(0).asInstanceOf[String]
log.d("FeedLoaderTask: doInBackground: " url)
val feeds = new FeedReader(url).extract
log.d("Got them, total: " feeds.length)
publishProgress()//feeds) // <--- seems to "call" but does not arrive
feeds
}
protected def onProgressUpdate(feeds: Seq[FeedEntry]): Void = {
// work damn you, WORK!
log.d("FeedLoaderTask: onProgressUpdate: " feeds.length)
return null
}
override protected def onPostExecute (feeds: Seq[FeedEntry]) {
dlgBusy.dismiss()
dlgBusy = null
feeds.length match {
case 0 => messageAndTerminate(R.string.rss_failed_msg)
case _ =>
listAdapter = new FeedListAdapter(...)
activity.setListAdapter(listAdapter)
...blah blah more code...
}
}
}
Итак, у меня есть обходной путь (может быть, даже лучший способ) делать то, что я хочу, но я ненавижу не иметь возможности делать то, что я хочу.
Было бы неплохо решить эту проблему, поскольку она меня победила … это мое первое приложение для Android, и я почти закончил его один раз на Java, но я так устал от всего набора текста и суеты, что начал с нуля и одновременно научился Scala. Я знаю Erlang, LISP и Haskell, так что это помогло. Все, что я могу сказать, это «ИЗУЧАЙТЕ SCALA СЕЙЧАС!»… поддержка XML потрясающая, мой оригинальный код синтаксического анализа RSS (четыре класса!) Теперь находится в одном файле и содержит около 80 строк кода, использующего XML API для поиска элементов, извлечения атрибутов и т. Д.
Всего наилучшего, 🙂
Ответ №1:
Я только что попробовал что-то подобное и, ну, столкнулся с той же проблемой, что и вы. Я решил это с помощью
определение класса как
class FeedLoaderTask(val activity: ActivityFeedReader)
extends AsyncTask[AnyRef, AnyRef, Seq[FeedEntry]]
и мой onProgressUpdate как:
override def onProgressUpdate(params: AnyRef*) {
val feeds = params(0).asInstanceOf[Seq[FeedEnty]]
...
}
Как вы можете видеть, это похоже на метод doInBackground() (обратите внимание, что вам не обязательно явно вызывать apply() в Scala, а методы void не требуют объявления возвращаемого типа и «=»).
Ответ №2:
защищенное переопределение onProgressUpdate(прогресс: Seq[FeedEntry] *) { }
Вероятно, вы хотите указать свою AsyncTask как AsyncTask[AnyRef, FeedEntry, Seq[FeedEntry]]
Итак, вы можете сделать
защищенное переопределение onProgressUpdate (каналы: FeedEntry *)
вместо
Ответ №3:
Полезно выполнить преобразование между аргументами и …. Создав новый класс Java, который смешивает оба, я мог бы добиться результата:
import scala.collection.mutable.ArrayBuffer;
import android.os.AsyncTask;
public abstract class MyAsyncTask<U, V, W> extends AsyncTask<U, V, W> {
@Override
protected W doInBackground(U ... args) {
int count = args.length;
ArrayBuffer<U> res = new ArrayBuffer<U>(count);
for (int i = 0; i < count; i ) {
res.$plus$eq(args[i]);
}
return doInBackground1(res);
}
// Method to override in the scala file
protected abstract W doInBackground1(ArrayBuffer<U> args);
ArrayBuffer<V> res = new ArrayBuffer<V>();
@Override
protected void onProgressUpdate(V ... args) {
int count = args.length;
res.ensureSize(count);
res.clear();
ArrayBuffer<V> res = new ArrayBuffer<V>(count);
for (int i = 0; i < count; i ) {
res.$plus$eq(args[i]);
}
onProgressUpdate1(res);
}
// Method to override in the scala file
protected abstract void onProgressUpdate1(ArrayBuffer<V> args);
}