Java noob在这里!我正在努力为我正在编写的Android应用程序添加点睛之笔。从本质上讲,它是一个RSS阅读器。异步任务获取RSS提要。然后解析它,我想要做的最后一点是用解析的RSS更新活动的ListView元素。
因为fetcher tast是异步的,所以它在它自己的类中,所以它无法直接更新UI(我相信)。
我的onPostExecute声明是:
public class getNews extends AsyncTask<String , Void ,String> {
String server_response;
// url fetch stuff is in here
}
protected void onPostExecute(String s) {
super.onPostExecute(s);
FullscreenActivity.updateNews(server_response)
}
FullscreenActivity.java类接收server_response并解析它:
public static void updateNews(String newsXML) {
// stuff goes on here, and I end up with a string array called headlines that
// contains the news headlines
}
当我尝试更新ListView时出现问题。如果我尝试在像这样的updateNews中这样做
ListView m_listview = (ListView) findViewById(R.id.ListViewRight);
我在findViewById下得到一个红色摇摆,说明非静态方法......无法从静态上下文中引用。
如果我使updateNews()非静态,我在onPostExecute例程中的updateNews下会发出一声红色的说法,说同样的话。
所以,我的问题是,在我的子例程声明中我需要什么样的混合口味才能让我从异步接收器,解析器和我的ListView中获取XML?
我完全被静态,私人,公众等所迷惑。即使在试图阅读它们之后,我也不是更聪明!
如果有任何帮助,我可以将整个项目发布到Github。我敢肯定,这不是一个如何看待Java的光辉榜样!
提前致谢, 伊恩
答案 0 :(得分:1)
因为fetcher tast是异步的,所以它在自己的类中,所以它不能直接更新UI(我相信)。
这取决于你的想法&#34;直接&#34;手段。如果您尝试从UI线程(也就是主线程)以外的任何线程更新View
,Android框架确实会崩溃您的应用程序。但AsyncTask
运行,例如UI线程上的onPostExecute()
因此更新此方法中的视图非常有效。
你说你的任务是#34;在它自己的班级&#34;,所以默认情况下你不能访问任何要更新的视图...但是你可以设置一些东西以便你< em> do 拥有此访问权限。
我完全被静电,私人,公众等所困惑。即使在试图阅读它们之后,我也没有明白的事情!
首先让我们谈谈private
和public
。这些被称为访问级别修饰符,您可以在此处详细了解它们:https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
但是,快速摘要应该足够了。如果某些东西是private
,那意味着可以使用它的唯一对象是相同类型的对象。如果某事是public
,那意味着任何人都可以使用它。
static
不同。此关键字定义您应用它的变量或方法是否是&#34;实例&#34;成员(没有static
关键字的东西)或&#34;类&#34;成员(具有static
关键字的内容)。同样,您可以在此处详细阅读:https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
而且,快速摘要应该足够了。如果某些内容为static
,则表示该类的所有实例共享。换句话说,它与&#34;的想法相关&#34;该类的特定实例,而不是该类的特定实例。否则,变量或方法仅与类的特定实例相关。
回到你的实际例子,我们可以谈谈这个方法:
public static void updateNews(String newsXML) {
...
}
此方法为static
,这意味着它由FullscreenActivity
的所有实例共享。它是public
,这意味着任何人都可以使用它。因此,AsyncTask
可以通过编写
FullscreenActivity.updateNews(server_response);
但是,如果您正在使用Android中的活动,则通常会关注特定活动实例的行为,而不是您对活动的一般概念。也就是说,您希望更新在用户手机上启动并运行的活动的屏幕,而不是所有可能存在的FullscreenActivity
个实例!
所以你应该把这个方法变成非静态的:
public void updateNews(String newsXML) {
...
}
现在这个方法是非静态的,你需要一个FullscreenActivity
实例来调用它。可以让你写下这个的东西:
activity.updateNews(server_response);
一种简单的方法是将您的活动传递给AsyncTask
的构造函数。
public class GetNews extends AsyncTask<String, Void, String> {
private FullscreenActivity activity;
public GetNews(FullscreenActivity activity) {
this.activity = activity;
}
...
protected void onPostExecute(String s) {
super.onPostExecute(s);
activity.updateNews(server_response);
}
}
现在,当您创建GetNews
实例时,而不是撰写new GetNews()
,您可以编写new GetNews(this)
(假设您在运行此代码时位于FullscreenActivity
内)。
答案 1 :(得分:0)
最糟糕的事情
public static void updateNews(String newsXML) {
//dunno what do you want to do here
}
不起作用,因为静态方法与类相关,但与实例无关。
您可以做的第一件事 - 将Activity
实例传递给您的AsyncTask
。
public class GetNews extends AsyncTask<String , Void ,String> {
String server_response;
FullscreenActivity activity;
public GetNews(FullscreenActivityactivity) {
this.activity = activity;
}
}
制作你的
public static void updateNews(String newsXML) {}
非static
public void updateNews(String newsXML) {}
所以你可以做你想做的事
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (activity != null)
activity.updateNews(server_response)
}
<强>更新强>
关于
ListView m_listview = (ListView) findViewById(R.id.ListViewRight);
为什么不将m_listview
作为Activity
类的字段并在onCreate
方法中实例化?
public class FullscreenActivityactivity extends Activity {
private ListView m_listview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
m_listview = (ListView) findViewById(R.id.ListViewRight);
}
}
答案 2 :(得分:0)
findViewById是一种非静态方法。这意味着它需要在Activity的实例上调用,并且不能在静态方法中调用。
通常,使用静态方法来更新您的Activity将无法正常工作(并且您可以通过破解它来使其工作的方式被认为是错误的想法并且通常会导致内存泄漏)。你的AsyncTask应该是你活动的内部类(在这种情况下它可以调用非静态更新函数),或者你应该在完成时传递一个接口来调用(你的活动应该传递一个调用updateList的接口)
答案 3 :(得分:0)
非常感谢你的帮助和解释。在此之后,我通过在我的活动类中添加几行代码来实现我的代码:
public class FullscreenActivity extends AppCompatActivity {
public static ListView m_listview;
public static Activity myThis;
然后在onCreate上,我添加了:
m_listview = (ListView) findViewById(R.id.ListViewRight);
myThis = this; // seems messy?
让我在需要时更新我的ListView:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(myThis, R.layout.listview_row_layout, R.id.firstLine, headlines);
m_listview.setAdapter(adapter);`
我会继续修补它。多年来我一直想学习Java和Android开发,现在我有一个项目要做。
我的背景是许多较旧的语言(主要是基本的)和一些脚本语言,如Perl。仍然认为Java是一个奇怪的野兽,但希望尽管我多年来变得更好! old_dog.new_tricks.teach(); :)