Android 单例

Singleton with Android

我在 android 工作室项目中正确使用单例模式时遇到了一些问题。我在我的 mainActivity class 中创建了一个 textView,我想在其中将该 textView 的文本设置为 GrouseSingleton class 中变量“a”的字符串值。但是,textView 始终显示为“hello”(它的初始化方式)而不是它应该是的实际字符串(它应该是“主要多云的天空”,从网站解析)。我假设我没有在单例 class 中正确设置变量“a”。任何帮助将不胜感激,谢谢!

单例 CLASS 代码:

public class GrouseSingleton extends AppCompatActivity {

private static GrouseSingleton instance = null;
public Document grouseWeather;
public String a = "hello";

private GrouseSingleton() throws IOException {
    startThread();
}

public static GrouseSingleton getInstance() throws IOException {
    if (instance == null) {
        instance = new GrouseSingleton();
    }
    return instance;

    }

    public void startThread() throws IOException {
        new Thread() {
            public void run() {
                try {
                    grouseWeather = Jsoup.connect("https://www.grousemountain.com/current_conditions#weather").get();
                    runOnUiThread( new Runnable()
                    {
                        public void run()
                        {
                            a = grouseWeather.select("h3.metric").first().text();
                            setA(a);
                        }
                    });

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }

    public void setA(String a) {
    this.a = a;
    }

}

主要活动代码:

     try {
         grouseSingleton = GrouseSingleton.getInstance();
     } catch (IOException e) {
         e.printStackTrace();
     }
     TextView tv45 = findViewById(R.id.textView45);
     tv45.setText(grouseSingleton.a);

你的单身人士没问题。问题是您创建了 class GrouseSingleton 的实例,然后您立即获得了 a 的值,这是默认值 "hello" 。因此,当从服务器获取 a 的值时,您需要使用如下所示的 interface 来通知您的 activity

public interface ResultListener {
    void onResultFetched(int textViewId, String txt);
}

在你的 Activity:

try {
     grouseSingleton = GrouseSingleton.getInstance(new ResultListener () {
        @Override
        public void onResultFetched(int textViewId, String txt) {
            TextView tv45 = findViewById(id);
            tv45.setText(txt);
        });
     grouseSingleton.startThread();
 } catch (IOException e) {
     e.printStackTrace();
 }
 

在您的 GrouseSingleton class:

中设置监听器
private static ResultListener listener;
public static GrouseSingleton getInstance(ResultListener listener) throws IOException {
    if (instance == null) {
        instance = new GrouseSingleton();
        GrouseSingleton.listener = listener;
    }
    return instance;
}


public void startThread() throws IOException {
    new Thread() {
        public void run() {
            try {
                grouseWeather = Jsoup.connect("https://www.grousemountain.com/current_conditions#weather").get();
                runOnUiThread( new Runnable()
                {
                    public void run()
                    {
                        a = grouseWeather.select("h3.metric").first().text();  
                        listener.onResultFetched(txtViewId, a);
                    }
                });

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }.start();

}

所有代码都很好。但问题是在加载数据 textview 之前设置默认值 hello。加载数据后,它无法更新该值。为了简单地实现这一点,只需在调用您的单身人士时将您的 textView 作为参数发送。喜欢:

单例类:

public class GrouseSingleton extends AppCompatActivity {

    private static GrouseSingleton instance = null;
    public Document grouseWeather;
    public String a = "hello";
    TextView textView;

    private GrouseSingleton(TextView textView) throws IOException {
        this.textView = textView;
        startThread();
    }

    public static GrouseSingleton getInstance(TextView textView) throws IOException {
        if (instance == null) {
            instance = new GrouseSingleton(textView);
        }
        return instance;

    }

    public void startThread() throws IOException {

        new Thread() {
            public void run() {
                try {
                    grouseWeather = Jsoup.connect("https://www.grousemountain.com/current_conditions#weather").get();
                    runOnUiThread( new Runnable()
                    {
                        public void run()
                        {
                            a = grouseWeather.select("h3.metric").first().text();
                            textView.setText(a);
                        }
                    });

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }
}

来自 MAinActivity:

TextView tv45 = findViewById(R.id.textView45);
try {
   grouseSingleton = GrouseSingleton.getInstance(tv45);
} catch (IOException e) {
   e.printStackTrace();
}
tv45.setText(grouseSingleton.a);