简体   繁体   中英

findViewById called from another class returns null sometimes

I'm having a wierd problem in my app. I am trying to update TextViews from another class (not the Activity). I can do it in two ways by calling overloaded getUpdate() methods:

This is how I call them from my MainActivity: This ways works fine.

public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    switch (id) {
        case R.id.menu_location_button:
            if (this.cwu == null)
                this.cwu = new CurrentWeatherUpdater(this);
            this.cwu.getUpdate(lf.getLongitude(), lf.getLatitude());
            break;
            .
            .
            .
    }
    return super.onOptionsItemSelected(item);
}

This one does not:

private void handleIntent(Intent intent) {
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        if (this.cwu == null)
            this.cwu = new CurrentWeatherUpdater(this);
        this.cwu.getUpdate(query);
    }
}

query is received from a SearchView

CurrentWeatherUpdater cwu; is declared in MainActivity.java

This is my CurrentWeatherUpdater class:

public class CurrentWeatherUpdater extends Updater{
private TextView city;
private TextView temp;
private TextView desc;
private TextView humidity;
private TextView pressure;
private TextView wind;

public CurrentWeatherUpdater(Context context) {
    super(context);
    this.city = (TextView) ((Activity)context).findViewById(R.id.city_name);
    this.temp = (TextView) ((Activity)context).findViewById(R.id.current_temperature);
    this.desc = (TextView) ((Activity)context).findViewById(R.id.current_weather_desc);
    this.humidity = (TextView) ((Activity)context).findViewById(R.id.humidity);
    this.pressure = (TextView) ((Activity)context).findViewById(R.id.pressure);
    this.wind = (TextView) ((Activity)context).findViewById(R.id.wind);
}

public void getUpdate(String cityName) {
    updateView(super.getUpdate(Updater.REQUEST_WEATHER, cityName));
}

public void getUpdate(double longitude, double latitude) {
    updateView(super.getUpdate(Updater.REQUEST_WEATHER, longitude, latitude));
}

private void updateView(JSONObject result) {
    try {
        if (result.getInt("cod") == 200) {
            this.city.setText(result.getString("name"));
            JSONObject main = result.getJSONObject("main");
            temp.setText(Integer.toString((int) Math.round(Double.parseDouble(main.getString("temp")))) + "\u00b0");
            pressure.setText(main.getString("pressure") + "hPa");
            humidity.setText(main.getString("humidity") + "%");
            JSONObject windInfo = result.getJSONObject("wind");
            wind.setText(windInfo.getString("speed") + "m/s");
            JSONArray weatherArray = result.getJSONArray("weather");
            JSONObject weather = weatherArray.getJSONObject(0);
            desc.setText(weather.getString("main"));
        } if (result.getInt("cod") == 404) {
            Toast.makeText(mContext, "Location not found", Toast.LENGTH_SHORT).show();
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

}

CurrentWeatherUpdater cwu; is declared in MainActivity.java

Basically when I call the CurrentWeatherUpdater(this) constructor from onOptionsItemSelected it works fine. But when I call it from doSearch , even though context points to MainActivity just like in the other one, none of the fields ( city , temp , etc.) is assigned a value and updateView method goes down in flames with NullPointerException on this.city.setText(result.getString("name"))

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference

Even when it first called from onOptionsItemSelected and the CurrentWeatherUpdater cwu object should already be created the if (this.cwu == null) evaluates to true and new object is created.

You could use LocalBroadcastManager to broadcast your data to another class

You could set data to LocalBroadcastManager by

Intent intent = new Intent("myFunction");
                // add data
                intent.putExtra("variable1", "Data1");
                intent.putExtra("variable2", "Data2");
                intent.putExtra("variable3", "Data3");
                LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

And Now in class where the update views are defined put this code:

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Extract data included in the Intent
            String t = intent.getStringExtra("variable1");
            String t1 = intent.getStringExtra("variable2");
            String t2 = intent.getStringExtra("variable3");
            //Updating textview function
            updateTheTextView(t, t1, t2);
        }
    };
    @Override
    public void onResume() {
        super.onResume();
        LocalBroadcastManager.getInstance(this.getActivity()).registerReceiver(mMessageReceiver,
                new IntentFilter("myFunction"));
    }

    @Override
    public void onPause() {
        super.onPause();
        LocalBroadcastManager.getInstance(this.getActivity()).unregisterReceiver(mMessageReceiver);
    }

I am not sure whether this helps you! But this is how i managed to send data to texviews defined in another class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM