Daniel
Daniel

Reputation: 783

Populate listview with an AsyncTask blocking UI and loads for a long time

Here is my Problem:

I have a fragment with a TextView for the search query, a button to start the search and a listview to show the results. I also use 2 custom Adapter because i have 2 search modes. When i press the searchbutton the asynctask should start working and populate the listview.

  1. Problem: The AsyncTask freezes the main thread :O
  2. Problem: The scrolling in the populated listview is very slowly..

I think its a problem with the adapter....any idea?

Fragment Class:

public class GesetzeFragment extends SherlockFragment {

private GesetzeFragment local;

EditText etSuchText;
ImageButton ibSuchen;
ListView lvResults;
ToggleButton tbModus;

private boolean paragraphenModus = false;

ArrayList<Gesetz> gesetzeItems = null;
ArrayList<Paragraph> paragraphItems = null;

GesetzeAdapter gesetzeAdapter = null;
ParagraphenAdapter paragraphAdapter = null;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    this.local = this;

    View v = inflater.inflate(R.layout.fragment_gesetze, container, false);

    tbModus = (ToggleButton) v.findViewById(R.id.toggleButton_modus);
    tbModus.setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton btn, boolean checked) {
            paragraphenModus = checked;
        }
    });

    etSuchText = (EditText) v.findViewById(R.id.editText_search_query);

    ibSuchen = (ImageButton) v.findViewById(R.id.imageButton_search);
    ibSuchen.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            onSearchAction(v);
        }
    });

    // Zeige zuerst 50 Gesetze
    lvResults = (ListView) v.findViewById(R.id.listView_search_results);

    lvResults.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

            // TODO: Paragraphenansicht öffnen
            Gesetz gesetz = (Gesetz) parent.getItemAtPosition(position);

        }

    });

    gesetzeItems = new ArrayList<Gesetz>();
    paragraphItems = new ArrayList<Paragraph>();

    paragraphAdapter = new ParagraphenAdapter(local.getActivity(),
            R.layout.paragraph_list_item, paragraphItems);
    gesetzeAdapter = new GesetzeAdapter(local.getActivity(),
            R.layout.gesetz_list_item, gesetzeItems);

    return v;
}

private void onSearchAction(View v) {
    lvResults.setAdapter(paragraphAdapter);

    LoadParagraphenTask task = new LoadParagraphenTask();
    task.execute(etSuchText.getText().toString(), 10);
}

private class LoadParagraphenTask extends
        AsyncTask<Object, Object, ArrayList<Paragraph>> {
    private final ProgressDialog dialog = new ProgressDialog(
            local.getActivity());

    @Override
    protected void onPreExecute() {

        dialog.setMessage("Suche...");
        dialog.show();

        super.onPreExecute();
    }

    @Override
    protected ArrayList<Paragraph> doInBackground(Object... params) {
        paragraphItems.clear();
        paragraphItems.addAll(Global.mGesetze.getParagraphen(
                (String) params[0], (Integer) params[1]));
        return paragraphItems;
    }

    @Override
    protected void onPostExecute(ArrayList<Paragraph> results) {
        paragraphAdapter.notifyDataSetChanged();

        dialog.dismiss();

        super.onPostExecute(results);
    }

}

private class LoadGesetzeTask extends
        AsyncTask<Object, Object, ArrayList<Gesetz>> {

    private final ProgressDialog dialog = new ProgressDialog(
            local.getActivity());

    @Override
    protected void onPreExecute() {

        dialog.setMessage("Suche...");
        dialog.show();

        super.onPreExecute();
    }

    @Override
    protected ArrayList<Gesetz> doInBackground(Object... params) {
        gesetzeItems.clear();
        gesetzeItems.addAll(Global.mGesetze.getGesetze((String) params[0],
                (Integer) params[1]));
        return gesetzeItems;
    }

    @Override
    protected void onPostExecute(ArrayList<Gesetz> results) {
        gesetzeAdapter.notifyDataSetChanged();

        dialog.dismiss();

        super.onPostExecute(results);
    }

}

public static GesetzeFragment newInstance(int info) {
    GesetzeFragment f = new GesetzeFragment();

    Bundle args = new Bundle();
    args.putInt("Info", info);
    f.setArguments(args);

    return f;
}
}

Xml File:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:orientation="vertical" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:orientation="vertical" >

    <ToggleButton
        android:id="@+id/toggleButton_modus"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textOff="Gesetze"
        android:textOn="Paragraphen" />

</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent" >

    <EditText
        android:id="@+id/editText_search_query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:ems="10"
        android:imeOptions="actionDone"
        android:inputType="text"
        android:singleLine="true" >

        <requestFocus />
    </EditText>

    <ImageButton
        android:id="@+id/imageButton_search"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:contentDescription="@+id/imageButton_search"
        android:scaleType="center"
        android:src="@drawable/ic_action_search_dark" />
</LinearLayout>

<ListView
    android:id="@+id/listView_search_results"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:clickable="true" >

</ListView>

One of the 2 Adapters:

public class ParagraphenAdapter extends ArrayAdapter<Paragraph>{

Context mContext;
int layoutResourceId;
ArrayList<Paragraph> items = null;

public ParagraphenAdapter(Context context, int textViewResourceId, ArrayList<Paragraph> objects) {
    super(context, textViewResourceId, objects);

    this.mContext = context;
    this.layoutResourceId = textViewResourceId;
    this.items = objects;

}

public ArrayList<Paragraph> getItems() {
    return items;
}

public void setItems(ArrayList<Paragraph> items) {
    this.items = items;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewsHolder mHolder = null;
    Paragraph item = items.get(position);

    if (convertView == null) // Wird zum ersten Mal gelanden...
    {
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        convertView = inflater.inflate(R.layout.paragraph_list_item, parent, false);

        mHolder = new ViewsHolder();
        mHolder.tvGesetzTitelShort = (TextView) convertView.findViewById(R.id.textView_gesetz_titel);
        mHolder.tvParagraphTitle = (TextView) convertView.findViewById(R.id.textView_paragraph_titel);
        mHolder.tvTextPreview = (TextView) convertView.findViewById(R.id.textView_preview_text);
        mHolder.btnFavorite = (ImageButton) convertView.findViewById(R.id.imageButton_favorite);

        convertView.setTag(mHolder);

    } else {
        mHolder = (ViewsHolder) convertView.getTag();
    }

    mHolder.tvGesetzTitelShort.setText(item.getGesetz().getNameShort());
    mHolder.tvParagraphTitle.setText(item.getParagraph());

    Spanned spannedContent = Html.fromHtml(item.getText());
    mHolder.tvTextPreview.setText(spannedContent, BufferType.SPANNABLE);

    return convertView;

}

static class ViewsHolder {
    TextView tvGesetzTitelShort;
    TextView tvParagraphTitle;
    TextView tvTextPreview;
    ImageButton btnFavorite;
}

}

The listitem:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:orientation="vertical" >

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#D8D8D8" >

    <ImageButton
        android:id="@+id/imageButton_favorite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:focusable="false"
        android:src="@android:drawable/btn_star_big_off" />

    <TextView
        android:id="@+id/textView_gesetz_titel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerHorizontal="false"
        android:layout_centerVertical="true"
        android:layout_toLeftOf="@id/imageButton_favorite"
        android:background="@android:color/transparent"
        android:padding="5dp"
        android:text="AO"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ffF2F2F2" >

    <TextView
        android:id="@+id/textView_paragraph_titel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:background="@android:color/transparent"
        android:maxLines="1"
        android:padding="5dp"
        android:text="§ 1"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

<TextView
    android:id="@+id/textView_preview_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:maxLines="3"
    android:padding="5dp"
    android:text="Bla bla Bla bla Bla bla Bla bla Bla bBla bla Bla bla Bla bla Bla bla Bla bla la Bla bla Bla bla Bla bla Bla bla " />

Upvotes: 0

Views: 883

Answers (1)

Juangcg
Juangcg

Reputation: 1048

I think the problem is in the call to:

 Spanned spannedContent = Html.fromHtml(item.getText());

This is a slow method. You should try to move this call to the AsyncTask, keep a copy within your Paragraph class, and then in the adapter just set the value.

Any other way, you will be making a slow task everytime the screen needs to refresh.

Upvotes: 1

Related Questions