NullPointerException由getActionBar()引起.setDisplayHomeAsUpEnabled(true);

时间:2017-05-07 02:02:07

标签: android android-fragments android-intent

我已经尝试了很多东西,但我的getActionBar()。setDisplayHomeAsUpEnabled(true);抛出空白

我还看到堆栈溢出的相对帖子,但它没有解决我的问题 我使用min SDK = 16并尝试从Mainactivity片段跳转到详细活动片段 我的意图很好,但在我的详细活动工具栏中,缺少后退按钮。 我的主要活动,我称之为jmp详细活动的意图 在setOnitemlistener方法中

package com.example.android.sunshine;

import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.format.Time;
import android.util.Log;    
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* A placeholder fragment containing a simple view.
*/
public class MainActivityFragment extends Fragment {
String LOG_TAG = MainActivityFragment.class.getSimpleName();
ArrayAdapter<String> mForecastAdapter;
public MainActivityFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
    inflater.inflate(R.menu.menuitem,menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item){
    int id = item.getItemId();
    if(id == R.id.action_refresh){
        FetchWeatherTask fetchWeatherTask = new FetchWeatherTask();

fetchWeatherTask.execute("Mathura","402c19fed0e53f9d92a81107ec2f6c2f");
    }
    return super.onOptionsItemSelected(item);
}



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView =  inflater.inflate(R.layout.fragment_main, container, 
false);
    String[] forecastArray = {
            "Sun May 1-CLEAR-31/17",
            "Mon May 1-CLEAR-31/17",
            "Tue May 1-CLEAR-31/17",
            "Wed May 1-CLEAR-31/17",
            "Thu May 1-CLEAR-31/17",
            "Fri May 1-CLEAR-31/17",
            "Sat May 1-CLEAR-31/17"
    };
    List<String> weekForecast = new ArrayList<String>
(Arrays.asList(forecastArray));
    mForecastAdapter = new ArrayAdapter<String>
(getActivity()
,R.layout.listitemforecast,
R.id.listitemforecastText,
weekForecast
);
    ListView listView = 
(ListView)rootView.findViewById(R.id.list_textView);
    listView.setAdapter(mForecastAdapter);

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int 
position, long id) {
            String forecast = mForecastAdapter.getItem(position);
           // Toast.makeText(getActivity(),forecast, 
Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(getActivity(),DetailActivity.class)
                    .putExtra(Intent.EXTRA_TEXT,forecast);
            try {
                startActivity(intent);
            }catch(Exception e)
            {
                Log.e(LOG_TAG,"error: "+ e);
            }
        }
    });
return rootView;
}


public class FetchWeatherTask extends AsyncTask<String,Void,String[]> {

    /* The date/time conversion code is going to be moved outside the 
asynctask later,
    * so for convenience we're breaking it out into its own method now.
    */
    private String getReadableDateString(long time){
        // Because the API returns a unix timestamp (measured in seconds),
        // it must be converted to milliseconds in order to be converted to 
valid date.
        SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE 
MMM dd");
        return shortenedDateFormat.format(time);
    }

    /**
     * Prepare the weather high/lows for presentation.
     */
    private String formatHighLows(double high, double low) {
        // For presentation, assume the user doesn't care about tenths of a 
degree.
        long roundedHigh = Math.round(high);
        long roundedLow = Math.round(low);

        String highLowStr = roundedHigh + "/" + roundedLow;
        return highLowStr;
    }

    /**
     * Take the String representing the complete forecast in JSON Format 
and
     * pull out the data we need to construct the Strings needed for the 
wireframes.
     *
     * Fortunately parsing is easy:  constructor takes the JSON string and 
converts it
     * into an Object hierarchy for us.
     */
    private String[] getWeatherDataFromJson(String forecastJsonStr, int 
numDays)
            throws JSONException {

        // These are the names of the JSON objects that need to be 
extracted.
        final String OWM_LIST = "list";
        final String OWM_WEATHER = "weather";
       // final String OWM_TEMPERATURE = "temp";
        final String OWM_MAX = "temp_max";
        final String OWM_MIN = "temp_min";
        final String OWM_DESCRIPTION = "main";

        JSONObject forecastJson = new JSONObject(forecastJsonStr);
        JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);

        // OWM returns daily forecasts based upon the local time of the 
city that is being
        // asked for, which means that we need to know the GMT offset to 
translate this data
        // properly.

        // Since this data is also sent in-order and the first day is 
always the
        // current day, we're going to take advantage of that to get a nice
        // normalized UTC date for all of our weather.

        Time dayTime = new Time();
        dayTime.setToNow();

        // we start at the day returned by local time. Otherwise this is a 
mess.
        int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), 
dayTime.gmtoff);

        // now we work exclusively in UTC
        dayTime = new Time();

        String[] resultStrs = new String[numDays];
        for(int i = 0; i < weatherArray.length(); i++) {
            // For now, using the format "Day, description, hi/low"
            String day;
            String description;
            String highAndLow;

            // Get the JSON object representing the day
            JSONObject dayForecast = weatherArray.getJSONObject(i);

            // The date/time is returned as a long.  We need to convert 
that
            // into something human-readable, since most people won't read 
"1400356800" as
            // "this saturday".
            long dateTime;
            // Cheating to convert this to UTC time, which is what we want 
anyhow
            dateTime = dayTime.setJulianDay(julianStartDay+i);
            day = getReadableDateString(dateTime);

            // description is in a child array called "weather", which is 1 
element long.
            JSONObject weatherObject = 
dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0);
            description = weatherObject.getString(OWM_DESCRIPTION);

            // Temperatures are in a child object called "temp".  Try not 
to name variables
            // "temp" when working with temperature.  It confuses 
everybody.
            JSONObject temperatureObject = 
dayForecast.getJSONObject(OWM_DESCRIPTION);
            double high = temperatureObject.getDouble(OWM_MAX);
            double low = temperatureObject.getDouble(OWM_MIN);

            highAndLow = formatHighLows(high, low);
            resultStrs[i] = day + " - " + description + " - " + highAndLow;
        }

        return resultStrs;
    }


        protected void onPostExecute(String[] Results){
            mForecastAdapter.clear();
            for(String day: Results){
                mForecastAdapter.add(day);
            }
        }







    protected String[] doInBackground(String... Params){

        String LOG_TAG = FetchWeatherTask.class.getSimpleName();
        // These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;

// Will contain the raw JSON response as a string.
        String forecastJsonStr = null;
        String format = "json";
        String units = "metric";
        int NumDays = 7;
        try {
            String Place = "q";
            String Mode = "mode";
            String cnt = "cnt";
            String Units = "units";
            String Appid = "APPID";
            // Construct the URL for the OpenWeatherMap query
            // Possible parameters are avaiable at OWM's forecast API page, 
at
            // http://openweathermap.org/API#forecast
            final String ForecastBaseURL = 
"http://api.openweathermap.org/data/2.5/forecast?";
            Uri builturi = Uri.parse(ForecastBaseURL).buildUpon()
                    .appendQueryParameter(Place,Params[0])
                    .appendQueryParameter(Mode,format)
                    .appendQueryParameter(cnt,Integer.toString(NumDays))
                    .appendQueryParameter(Units,units)
                    .appendQueryParameter(Appid,Params[1]).build();
            URL url = new URL(builturi.toString());
           // Log.v(LOG_TAG,"Built URI:"+builturi.toString());
            // Create the request to OpenWeatherMap, and open the 
connection
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            // Read the input stream into a String
            InputStream inputStream = urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();
            if (inputStream == null) {
                // Nothing to do.
                return null;
            }
            reader = new BufferedReader(new 
InputStreamReader(inputStream));

            String line;
            while ((line = reader.readLine()) != null) {
                // Since it's JSON, adding a newline isn't necessary (it 
won't affect parsing)
                // But it does make debugging a *lot* easier if you print 
out the completed
                // buffer for debugging.
                buffer.append(line + "\n");
            }

            if (buffer.length() == 0) {
                // Stream was empty.  No point in parsing.
                forecastJsonStr = null;
            }
            forecastJsonStr = buffer.toString();
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error ", e);
            // If the code didn't successfully get the weather data,  
there's no point in attemping
            // to parse it.
            forecastJsonStr = null;
        } finally{
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (final IOException e) {
                    Log.e(LOG_TAG, "Error closing stream", e);
                }
            }
        }
        try{
            return getWeatherDataFromJson(forecastJsonStr,NumDays);
        }catch (JSONException e){
            Log.e(LOG_TAG,"json error" + e);
        }

     return null;
    }
}
}

我的详细活动:

package com.example.android.sunshine;

import android.app.Activity;
import android.os.Bundle;

public class DetailActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_detail);
    if(getActionBar() != null){
        getActionBar().setDisplayHomeAsUpEnabled(true);  // Here its 
throwing null
    }
}

}

我的详细信息fragment.java

package com.example.android.sunshine;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

 /**
 * A placeholder fragment containing a simple view.
 */
public class  DetailActivityFragment extends Fragment {

public DetailActivityFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootview = inflater.inflate(R.layout.fragment_detail, container, 
false);
    Intent intent = getActivity().getIntent();
    if(intent != null && intent.hasExtra(Intent.EXTRA_TEXT))
    {
        String forecast = intent.getStringExtra(Intent.EXTRA_TEXT);
        ((TextView)rootview.findViewById(R.id.detail_text))
                .setText(forecast);

    }

    return rootview;
}
}

我的主要活动:

package com.example.android.sunshine;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) 
findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", 
Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is 
present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

我的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.sunshine">
<uses-permission android:name="android.permission.INTERNET" />


<application
    android:allowBackup="true"
    android:icon="@drawable/sunshine"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".DetailActivity"
        android:label="@string/title_activity_detail"
        android:theme="@style/AppTheme.NoActionBar"
        android:parentActivityName=".MainActivity">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.android.sunshine.MainActivity" />
    </activity>
</application>

</manifest>

4 个答案:

答案 0 :(得分:1)

与AndroidManifest.xml一样,您的活动使用没有操作栏的主题:      <activity android:name=".DetailActivity" android:label="@string/title_activity_detail" android:theme="@style/AppTheme.NoActionBar" android:parentActivityName=".MainActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.android.sunshine.MainActivity" /> </activity>

因此,您可以更改主题以解决问题。

答案 1 :(得分:0)

您的DetailActivity应该扩展AppCompatActivity

package com.example.android.sunshine;

import android.app.Activity;
import android.os.Bundle;

public class DetailActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_detail);
    if(getActionBar() != null){
        getActionBar().setDisplayHomeAsUpEnabled(true);  
    }
}

}

答案 2 :(得分:0)

删除DetailActivtity中的这部分代码

if(getActionBar() != null){
    getActionBar().setDisplayHomeAsUpEnabled(true);  
}

在onCreate方法之后实现此方法,您的后退按钮将会启动并开始工作。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            finish();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
} 

答案 3 :(得分:0)

您需要扩展 AppCompatActivity ,详细信息活动

package com.example.android.sunshine; 

import android.app.Activity;
import android.os.Bundle;

public class DetailActivity extends AppCompatActivity { 

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

    if(getSupportActionBar() != null){
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

} 

}

并检查您的样式文件

<style name="Theme.AppCompat.NoActionBar.FullScreen" parent="AppTheme">
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>