我目前有一个Pollen类,它是我编写的一个类,它使用JSoup库来解析HTML。此处还显示了我的PlaceholderFragment
类。
public static class PlaceholderFragment extends Fragment
{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
final Button button = (Button) rootView.findViewById(R.id.button1);
final TextView textview = (TextView) rootView.findViewById(R.id.textview1);
button.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Pollen pollenObject = new Pollen(19104);
textview.setText(pollenObject.getCity());
}
});
return rootView;
}
}
这是我的Pollen课程。
public static class Pollen
{
@SuppressLint("SimpleDateFormat")
public Pollen(int zipcode)
{
this.zipcode = zipcode;
Document doc;
try
{
// pass address to
doc = Jsoup.connect("http://www.wunderground.com/DisplayPollen.asp?Zipcode=" + this.zipcode).get();
// get "location" from XML
Element location = doc.select("div.columns").first();
this.location = location.text();
// get "pollen type" from XML
Element pollenType = doc.select("div.panel h3").first();
this.pollenType = pollenType.text();
SimpleDateFormat format = new SimpleDateFormat("EEE MMMM dd, yyyy");
// add the four items of pollen and dates
// to its respective list
for(int i = 0; i < 4; i++)
{
Element dates = doc.select("td.text-center.even-four").get(i);
Element levels = doc.select("td.levels").get(i);
try
{
pollenMap.put(format.parse(dates.text()), levels.text());
}
catch (ParseException e)
{
e.printStackTrace();
}
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我在尝试失败的过程中学到了很多东西。我发现,在Pollen
中调用我的onClick
类时,我正在做一项昂贵的任务。因此,我应该把它放在一个单独的线程中。要添加,因为我在main / UI线程中调用我的Pollen
类,它会导致我的应用程序崩溃。
我咨询了Stackoverflow这个问题,帮助我尝试解决我的问题:How to fix android.os.NetworkOnMainThreadException?
我通过这个来自logcat的错误日志发现了我的错误和解决方案,特别是NetworkOnMainThread
,其中Android显然阻止我在我的UI线程上做任何网络。
我的问题是 - 如何将我的Pollen
类分配到不属于我的UI类的单独线程中?
继续我关于Stackoverflow线程的教程,我添加了这个类。我不知道我在做什么......但我会尽力继续:
abstract class RetrievePollenTask extends AsyncTask<Integer, Void, Pollen>
{
protected Pollen doInBackground(String... params)
{
// TODO Auto-generated method stub
return null;
}
}
答案 0 :(得分:1)
是的,您正在尝试在UI线程内部进行网络连接,这是非法的并且会捕获NetworkOnMainThreadException
的异常。
您可以使用正在执行的AsyncTask
而不是在主线程内部连接,但它不应该是抽象的,它只是一个普通的类,因此您可以执行AsyncTask
..
示例:
public class RetrievePollenTask extends AsyncTask<Integer, Void, Pollen>
{
protected Pollen doInBackground(String... params)
{
Pollen pollenObject = new Pollen(19104);
return pollenObject;
}
protected void onPostExecute(Pollen result) {
textview.setText(pollenObject.getCity());
}
}
你可以使你的asynctask成为你片段的内部类,所以你不需要在它上面传递context参数。也不要更新任何视图insidte doInBackground
因为它是一个不同的线程,它将捕获异常。
答案 1 :(得分:0)
这是AsyncTask
的{{3}}。您必须使用AsyncTask
执行所有网络操作。
它基本上有3种方法
onPreExecute()
doInBackground()
onPostExecute()
使用doInBackground()
方法执行网络操作。更新onPostExecute()
class RetrievePollenTask extends AsyncTask<Integer, Void, Pollen>
{
@Override
protected Pollen doInBackground(Integer zip)
{
// TODO Auto-generated method stub
Pollen pollenObject = new Pollen(zip);
return pollenObject;
}
@Override
protected void onPostExecute(Pollen pollenObject) {
textView.setText(pollenObject.getCity());
}
}
在PlacholderFragment
班级
button.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
RetrievePollenTask object = new RetrievePollenTask();
object.execute(19104);
}
});
答案 2 :(得分:0)
AsyncTask
是Android框架提供的一种机制,可以在不阻塞主UI线程的情况下方便执行长时间运行的任务。阅读Android开发者网站上的Keeping Your Apps Responsive教程,了解有关此主题的详细信息。
This链接可帮助您使用AsyncTask
机制重新设计课程。
希望这有帮助
答案 3 :(得分:0)
AsyncTask
用于在非UI线程中运行代码,但也有可与您的UI交互的方法。
AsyncTask<String, Integer, Pollen>
这定义了AsyncTask使用的对象。如果不使用任何对象,请使用Void
。
doInBackground()
的输入。onProgressUpdate()
用于定期更新用户进度的参数doInBackground()
这些参数声明为Object... vars
,实际上是您可以使用vars[index]
访问的数组。如果您只传递一个变量,请使用var[0]
Here is the official documentation
class RetrievePollenTask extends AsyncTask<String, Integer, Pollen>
{
@Override
protected void onPreExecute() {
// set up a ProgressBar or other UI action here *before* the task runs
}
@Override
protected Pollen doInBackground(String... params)
{
// perform your separate non UI thread actions here
// call publishProgress(int) to update your UI periodically
return pollenObject;
}
@Override
protected void onProgessUpdate(Integer... progress) {
// update your UI or ProgressBar
}
@Override
protected void onPostExectute(Pollen resultReturned)
// back to the UI thread again here to update Views or cancel your ProgressBar etc
// this executes *after* your task has completed
// it receives its argument from the return of doInBackground() so you can use that when updating your UI.
}
}
答案 4 :(得分:0)
经验法则:
doInBackground()
,在后台线程中执行。onPostExecute()
,一旦后台操作完成,就会在UI线程中执行。在您的示例中,这可能是您可以编写的最简单的代码:
button.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
AsyncTask<Integer, Void, Pollen> loadPollen = new AsyncTask<Integer, Void, Pollen>()
{
@Override
protected Pollen doInBackground(Integer... params)
{
return new Pollen(params[0]);
}
@Override
protected void onPostExecute(Pollen result)
{
textview.setText(result.getCity());
}
};
loadPollen.execute(19104);
}
});