You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中基于Volley实现返回JSONObject的方法及自定义观察者模式改造方案

Custom Observer Pattern Implementation for Weather App (No Android Built-in Observer)

Got it, let's walk through implementing a custom observer pattern for your weather app—no Android built-in Observer interface required. This setup will let MainActivity hold the latest weather JSONObject as the "subject", and your displayInfo activity act as an "observer" that gets notified when new data arrives, or can actively fetch the latest data whenever it needs.


Step 1: Define the Observer Interface

First, create a simple interface to standardize how observers react to weather data updates. All observers will implement this interface.

// Create this as a separate Java file or inside MainActivity
public interface WeatherDataObserver {
    // Called when new weather data is available
    void onWeatherDataUpdated(JSONObject latestWeatherData);
}

Step 2: Modify MainActivity to Act as the Subject

Update MainActivity to manage a list of observers, store the latest weather JSONObject, and handle notifications. Here's how to adjust your existing code:

public class MainActivity extends AppCompatActivity {
    // Your existing variables (searchBar, leftApiUrl, rightApiUrl, etc.)
    private List<WeatherDataObserver> observers = new ArrayList<>();
    private JSONObject latestWeatherJson; // Holds the most recent weather data

    // Register an observer to receive updates
    public void registerObserver(WeatherDataObserver observer) {
        if (!observers.contains(observer)) {
            observers.add(observer);
            // Send existing data immediately if we already have it
            if (latestWeatherJson != null) {
                observer.onWeatherDataUpdated(latestWeatherJson);
            }
        }
    }

    // Remove an observer (critical to avoid memory leaks)
    public void unregisterObserver(WeatherDataObserver observer) {
        observers.remove(observer);
    }

    // Notify all registered observers of new data
    private void notifyObservers() {
        for (WeatherDataObserver observer : observers) {
            observer.onWeatherDataUpdated(latestWeatherJson);
        }
    }

    // Public method for observers to actively fetch the latest data
    public JSONObject getLatestWeatherData() {
        return latestWeatherJson;
    }

    // Update your existing getInfoMethod() to save data and notify observers
    public void getInfoMethod(){
        String finalUrl ="";
        String cityName = searchBar.getText().toString().trim();
        RequestQueue rQ = Volley.newRequestQueue(getApplicationContext());
        finalUrl = leftApiUrl+cityName+rightApiUrl;
        
        StringRequest sR = new StringRequest(Request.Method.POST, finalUrl, 
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    try {
                        JSONObject allJsonRes = new JSONObject(response);
                        // Save the latest JSON data to our member variable
                        latestWeatherJson = allJsonRes;
                        // Notify all observers about the new data
                        notifyObservers();

                        // You can remove the old Intent.putExtra code here—we're using the observer pattern now
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }, 
            new Response.ErrorListener(){
                @Override
                public void onErrorResponse(VolleyError error) {
                    Toast.makeText(getApplicationContext(),"Error,check network or spelling",Toast.LENGTH_SHORT).show();
                }
            });
        rQ.add(sR);
    }
}

Step 3: Modify displayInfo to Act as the Observer

Make displayInfo implement the WeatherDataObserver interface, register itself with MainActivity, and update its UI when data changes.

public class displayInfo extends AppCompatActivity implements WeatherDataObserver {
    // Initialize your TextViews (match your layout IDs)
    private TextView cityNameTv;
    private TextView tempTv;
    private TextView mainDescTv;
    // ... add other TextViews you need

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.your_display_info_layout);

        // Initialize UI elements
        cityNameTv = findViewById(R.id.city_name_tv);
        tempTv = findViewById(R.id.temp_tv);
        mainDescTv = findViewById(R.id.main_desc_tv);
        // ... initialize other TextViews

        // Register this activity as an observer to MainActivity
        // Note: If you start displayInfo from MainActivity, you can get the reference via getParent()
        // For production apps, consider using a singleton Subject or ViewModel for safer communication
        MainActivity mainActivity = (MainActivity) getParent();
        if (mainActivity != null) {
            mainActivity.registerObserver(this);
            
            // Optionally: Actively fetch the latest data right away if it exists
            JSONObject latestData = mainActivity.getLatestWeatherData();
            if (latestData != null) {
                updateUI(latestData);
            }
        }
    }

    @Override
    public void onWeatherDataUpdated(JSONObject latestWeatherData) {
        // Update the UI with the new weather data
        updateUI(latestWeatherData);
    }

    private void updateUI(JSONObject weatherData) {
        try {
            // Parse data from the JSONObject (reuse your existing parsing logic)
            String cityName = weatherData.getString("name");
            double temp = weatherData.getJSONObject("main").getDouble("temp");
            String mainDesc = weatherData.getJSONArray("weather").getJSONObject(0).getString("main");
            // ... parse all other fields you need

            // Update TextViews
            cityNameTv.setText(cityName);
            tempTv.setText(Math.round(temp) + "°C");
            mainDescTv.setText(mainDesc);
            // ... update other UI elements
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Unregister the observer to prevent memory leaks
        MainActivity mainActivity = (MainActivity) getParent();
        if (mainActivity != null) {
            mainActivity.unregisterObserver(this);
        }
    }
}

Key Notes for Robustness

  • Memory Leak Prevention: Always unregister observers in onDestroy()—this ensures MainActivity doesn't hold references to destroyed activities.
  • Thread Safety: If you ever modify the observer list from a background thread, use a thread-safe list like CopyOnWriteArrayList instead of ArrayList.
  • Alternative Communication: For more complex app flows, consider using a singleton WeatherDataSubject class or Android ViewModel to manage the observer list and data—this avoids relying on getParent() which can be fragile.

内容的提问来源于stack exchange,提问作者MUCHUAN SU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 02:39:08