Reputation: 33
I'm trying to change fonts of listview items. Without AsyncTasc it takes too much time. Using AsyncTask activity with that listview emerges fast and then after instance application crashes. I know that I can't change UI from AsyncTasc directly.What could I use? Thanks in advance
import ru.ayratbadykov.feedhandler.FEED;
import ru.ayratbadykov.feedhandler.RssMessage;
import android.content.Context;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class CustomAdapter extends BaseAdapter {
private FEED _data;
Context _c;
CustomAdapter(FEED data, Context c) {
_data = data;
_c = c;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.w("here","here");
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) _c
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.customadapter, null);
}
TextView fromView = (TextView) v.findViewById(R.id.textView1);
TextView subView = (TextView) v.findViewById(R.id.textView2);
TextView View = (TextView) v.findViewById(R.id.textView3);
RssMessage msg = _data.getMessages().get(position);
new Font().execute(fromView,subView,View);
fromView.setText(msg.getTitle());
subView.setText(msg.getPUBDATE());
View.setText(_data.getTitle());
return v;
}
public class Font extends AsyncTask<TextView, Void, Boolean> {
@Override
protected Boolean doInBackground(TextView... params) {
// TODO Auto-generated method stub
String fontPath = "fonts/Qlassik_TB.ttf";
Typeface tf = Typeface.createFromAsset(_c.getAssets(), fontPath);
params[0].setTypeface(tf);
fontPath="fonts/damase.ttf";
tf = Typeface.createFromAsset(_c.getAssets(), fontPath);
params[1].setTypeface(tf);
tf = Typeface.createFromAsset(_c.getAssets(), fontPath);
params[3].setTypeface(tf);
return true;
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return _data.getMessages().size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return _data.getMessages().get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
}
log
05-31 22:32:27.602: E/AndroidRuntime(2803): FATAL EXCEPTION: AsyncTask #1
05-31 22:32:27.602: E/AndroidRuntime(2803): java.lang.RuntimeException: An error occured while executing doInBackground()
05-31 22:32:27.602: E/AndroidRuntime(2803): at android.os.AsyncTask$3.done(AsyncTask.java:200)
05-31 22:32:27.602: E/AndroidRuntime(2803): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
05-31 22:32:27.602: E/AndroidRuntime(2803): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
05-31 22:32:27.602: E/AndroidRuntime(2803): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
05-31 22:32:27.602: E/AndroidRuntime(2803): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
05-31 22:32:27.602: E/AndroidRuntime(2803): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
05-31 22:32:27.602: E/AndroidRuntime(2803): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
05-31 22:32:27.602: E/AndroidRuntime(2803): at java.lang.Thread.run(Thread.java:1019)
05-31 22:32:27.602: E/AndroidRuntime(2803): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-31 22:32:27.602: E/AndroidRuntime(2803): at android.os.Handler.<init>(Handler.java:121)
05-31 22:32:27.602: E/AndroidRuntime(2803): at ru.ayratbadykov.rssunion.CustomAdapter$Font$1.<init>(CustomAdapter.java:63)
05-31 22:32:27.602: E/AndroidRuntime(2803): at ru.ayratbadykov.rssunion.CustomAdapter$Font.doInBackground(CustomAdapter.java:63)
05-31 22:32:27.602: E/AndroidRuntime(2803): at ru.ayratbadykov.rssunion.CustomAdapter$Font.doInBackground(CustomAdapter.java:1)
05-31 22:32:27.602: E/AndroidRuntime(2803): at android.os.AsyncTask$2.call(AsyncTask.java:185)
05-31 22:32:27.602: E/AndroidRuntime(2803): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
05-31 22:32:27.602: E/AndroidRuntime(2803): ... 4 more
Upvotes: 0
Views: 1477
Reputation: 1783
Conisder solution not to create font from asset for every field. Make static method returning Typeface, for example. I'm setting fonts for list elements with no performance problems in UI thread.
for example:
public class CustomAdapter extends BaseAdapter {
static Typeface mFont = YourClass.getDefaultTypeFace();
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
TextView tv;
...
tv.setTypeface(mFont);
...
}
}
Also, there are some issues with memory allocation for font assets, don't create multiply instances of Typeface. Check this, works perfect for me: To use or not to use Custom Fonts on Android
Upvotes: 0
Reputation: 133560
You cannot update ui on the background thread. doInBackground is invoked on the background thread. You should update ui on the ui thread.
You are trying to update textview in doInBackground. Use runOnUiThread if you need to update ui inside doInBackground().
I am also not sure why you require a asynctask for what you are doing.
runOnUiThread(new Runnable(){
@Override
public void run(){
//update ui here
}
});
onPreExecute(),onPostExecute(Result), are invoked on the ui thread. So you can update ui here.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). can be used to animate a progress bar or show logs in a text field.
The result of doInbackground() computation is a parameter to onPostExecute(Result) so return the result in doinBackground() and show your toast in onPostExecute(Result)
For clarity check the link below under the topic The 4 steps.
http://developer.android.com/reference/android/os/AsyncTask.html
You can also use a handler for this purpose.
http://developer.android.com/reference/android/os/Handler.html
Upvotes: 0
Reputation: 1547
An AsyncTask allows you both to start a long process and access UI via the UIThread methods:
You have everything you need to do if you understand the operation of an Asynctask
Upvotes: 0
Reputation: 44571
You can update UI
in AsyncTask
just not from doInBackground()
. But any other methods are fine. And since it is an inner class of your Adapter
class which holds a reference to the Context
then it is fine to do. Just move the code that uses Context
or needs to update the UI
to any other method.
For example, you could return an ArrayList
of the params
to onPostExecute()
and update there or you could use publishProgress()
and update them in onProgressUpdate()
So also has a lot of good examples of using each
Upvotes: 1