在 java 类 周围传递数据

Passing data around java classes

Java菜鸟来了!我正在努力为我正在编写的 Android 应用程序画龙点睛。本质上,它是一个 RSS reader。异步任务获取 RSS 提要。然后对其进行解析,我想做的最后一点是用解析后的 RSS 更新 activity 的 ListView 元素。

因为 fetcher tast 是异步的,它在自己的 class 中,所以它不能直接更新 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 class 收到 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 下看到一个红色的摆动,说同样的话。

所以,我的问题是,在我的子例程声明中我需要什么样的风格组合才能让我通过解析器从我的异步接收器中获取 XML 并进入我的 ListView?

我对静态、私有、公共等完全感到困惑。即使在尝试阅读它们之后,我还是 none 更聪明!

如果有任何帮助,我可以 post 整个项目到 Github。我敢肯定这不是 java 应该是什么样子的光辉榜样!

提前致谢, 伊恩

最糟糕的是

public static void updateNews(String newsXML) {
    //dunno what do you want to do here    
}

将不起作用,因为静态方法与 class 有关,但与 instance.

无关

您可以做的第一件事 - 将 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 class 的字段并在 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);
        }
}

findViewById 是一个非静态方法。这意味着它需要在 Activity 的实例上调用,不能在静态方法中调用。

一般来说,使用静态方法来更新您的 Activity 是行不通的(您破解它以使其工作的方法被认为是糟糕的想法,通常会导致内存泄漏)。您的 AsyncTask 应该是 activity 的内部 class (在这种情况下它可以调用非静态更新函数),或者您应该向它传递一个接口以在完成时调用(以及您的 activity 应该向它传递一个调用 updateList 的接口)。

Because the fetcher tast is asynchronous, it's in its own class, so it can't update the UI directly (I believe).

这完全取决于您认为 "directly" 的意思。如果您尝试从 UI 线程(也称为主线程)以外的任何线程更新 View,Android 框架确实会使您的应用程序崩溃。但是 AsyncTask 运行s 例如onPostExecute() 在 UI 线程上,因此在此方法中更新视图是完全有效的。

您说您的任务是 "in its own class",因此默认情况下您将无权访问任何要更新的视图...但您可以进行设置,以便 执行 有这个权限。

I'm totally confused by statics, privates, publics etc. Even after trying to read about them I'm none the wiser!

先说一下privatepublic。这些被称为 访问级别修饰符,您可以在此处详细了解它们:https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

但是,快速总结应该就足够了。如果某物是 private,这意味着唯一可以使用它的对象是相同类型的对象。如果某个东西是 public,那意味着任何人都可以使用它。

static不一样。此关键字定义您应用它的变量或方法是 "instance" 成员(没有 static 关键字的东西)还是 "class" 成员(带有 static 的东西关键词)。同样,您可以在此处详细阅读:https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

而且,再一次,快速总结就足够了。如果某物是 static,则意味着它 由该 class 的所有实例共享。换句话说,它与 class 的 "idea" 有关,而不是 class 的特定实例。否则,变量或方法仅与 class.

的特定实例相关

回到你的实际例子,我们可以谈谈这个方法:

public static void updateNews(String newsXML) {
    ...
}

这个方法是static,这意味着它被FullscreenActivity的所有实例共享。它是 public,这意味着任何人都可以使用它。所以你的 AsyncTask 可以通过写

轻松调用它
FullscreenActivity.updateNews(server_response);

但是当您在 Android 中处理活动时,您通常会关心 activity 的特定实例的行为,而不是 activity 的一般概念=].也就是说,您想在用户的 phone 上更新 activity 和 运行ning 的屏幕,而不是所有可能存在的 FullscreenActivity 实例!

所以你应该使这个方法成为非静态的:

public void updateNews(String newsXML) {
    ...
}

现在这个方法是非静态的,您需要一个 FullscreenActivity 实例来调用它。可以让你写这个的东西:

activity.updateNews(server_response);

一个简单的方法是将 activity 传递给 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(this) 而不是编写 new GetNews()(假设您在 FullscreenActivity 中 运行 这个代码)。

非常感谢大家的帮助和解释。在此之后,我通过向我的 activity class:

添加几行来使我的代码正常工作
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(); :)