2016-03-03 56 views
0

我想让我的微调保存它的位置,当屏幕转动。我试着按照解决方案​​,但它不起作用,并给我一个nullpointerexception。任何想法如何解决它?微调不保存选定的项目旋转

package tk.talcharnes.popularmovies; 

import android.content.Intent; 
import android.net.Uri; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.view.MenuItemCompat; 
import android.util.DisplayMetrics; 
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.GridView; 
import android.widget.Spinner; 
import android.widget.Toast; 

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.MalformedURLException; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.List; 

/** 
* A placeholder fragment containing a simple view. 
*/ 
public class PostersFragment extends Fragment { 
    private static List<MovieModel> movieModelList; 
    private static int movieModelListLength; 
    GridView gridView; 
    ImageAdapter adapter; 
    Spinner spinner; 
    private String sort_method; 
    public PostersFragment() { 
     //sort_method = "popularity.desc"; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_main, container, false); 

      updatePosters(); 
     // should find gridview on the view which you are creating 
     gridView = (GridView) view.findViewById(R.id.gridview); 



     DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); 
     int width = (int) (displayMetrics.widthPixels/displayMetrics.density); 
// 
//  //For Tabs 
////  boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; 
////  width = isLandscape ? (width/2) : width; 
//  int numcolumns =(int) (width/(185)); 
//// 
////  float dpHeight = displayMetrics.heightPixels/displayMetrics.density; 
////  float dpWidth = displayMetrics.widthPixels/displayMetrics.density; 
////  int numcolumns = (int)((185*dp)/dpWidth); 
//  gridView.setNumColumns(numcolumns); 
     if (getResources().getConfiguration().orientation 
       == 1) { 
      gridView.setNumColumns(2); 


     } else if (getResources().getConfiguration().orientation 
       == 2) { 
      gridView.setNumColumns(3); 

     } 

     adapter = new ImageAdapter(getContext()); 
     gridView.setAdapter(adapter); 
     updatePosters(); 
     gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      public void onItemClick(AdapterView<?> parent, View v, 
            int position, long id) { 
       Toast.makeText(getContext(), "You clicked " + movieModelList.get(position).getTitle(), 
         Toast.LENGTH_SHORT).show(); 
       MovieModel movieModel = movieModelList.get(position); 
       Intent intent = new Intent(getActivity(), MovieDetails.class); 
       intent.putExtra("Movie_number", position); 
       startActivity(intent); 

      } 
     }); 
     return view; 
    } 

    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putInt("spinner", spinner.getSelectedItemPosition()); 
    } 

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

     if(savedInstanceState != null) { 
      spinner.setSelection(savedInstanceState.getInt("spinner", 0)); 
     } 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     //commented out until a settings menu is implemented 
     // super.onCreateOptionsMenu(menu, inflater); 
     // getActivity().getMenuInflater().inflate(R.menu.menu_main, menu); 
     inflater.inflate(R.menu.menu_refresh, menu); 


     MenuItem item = menu.findItem(R.id.spinnerr); 
     spinner = (Spinner) MenuItemCompat.getActionView(item); 


     String[] sortingCriteria = {"Popular", "Highest Rated"}; 
     ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(getContext(), R.layout.spinner, sortingCriteria); 
     spinner.setAdapter(spinnerAdapter); 
     spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 
      @Override 
      public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) { 
       if(position == 0){ 
        sort_method = "popularity.desc"; 
        updatePosters(); 
       } 
       else if (position == 1){ 
        sort_method = "vote_average.desc"; 
        updatePosters(); 
       } 
      } 

      @Override 
      public void onNothingSelected(AdapterView<?> parentView) { 
       // does nothing 
      } 

     }); 

    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 

     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 

     if (id == R.id.action_refresh) { 
      Toast.makeText(getActivity(), "Refreshing", 
        Toast.LENGTH_SHORT).show(); 

      updatePosters(); 
      gridView.setAdapter(adapter); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
    public void updatePosters(){ 
     FetchPostersTask updatePosters = new FetchPostersTask(); 
     updatePosters.execute(); 
    } 









    //Get movie posters and data 
    public class FetchPostersTask extends AsyncTask<Void,Void,Void> { 
     private final String LOG_TAG = FetchPostersTask.class.getSimpleName(); 
     //will contain raw Json data 
     String posterJsonString = null; 

     public Void parseMovieJson() 
       throws JSONException{ 
      JSONObject jsonParentObject = new JSONObject(posterJsonString); 
      JSONArray movieJSonArray = jsonParentObject.getJSONArray("results"); 

      movieModelList = new ArrayList<>(); 
      for(int i = 0; i < movieJSonArray.length(); i++){ 
       JSONObject movieJsonObject = movieJSonArray.getJSONObject(i); 
       MovieModel movieModel = new MovieModel(); 
       movieModel.setTitle(movieJsonObject.getString("title")); 
       movieModel.setOverview(movieJsonObject.getString("overview")); 
       movieModel.setPoster_path(movieJsonObject.getString("poster_path")); 
       movieModel.setRelease_date(movieJsonObject.getString("release_date")); 
       movieModel.setVote_average(movieJsonObject.getString("vote_average")); 
       movieModelListLength++; 

       movieModelList.add(movieModel); 
      } 
      return null; 
     } 

     @Override 
     protected Void doInBackground(Void ...params) { 

      HttpURLConnection urlConnection = null; 
      BufferedReader reader = null; 

      //will contain raw Json data 
      try{ 

       //open connection to api 

       final String BASE_URL = "https://api.themoviedb.org/3/discover/movie?"; 
       final String SORT_PARAM ="sort_by"; 



       Uri builtUri = Uri.parse(BASE_URL).buildUpon() 
         .appendQueryParameter(SORT_PARAM, sort_method) 
         .appendQueryParameter("api_key", BuildConfig.MOVIE_DB_API_KEY).build(); 

       URL url = new URL(builtUri.toString()); 
       urlConnection = (HttpURLConnection) url.openConnection(); 
       urlConnection.setRequestMethod("GET"); 
       urlConnection.connect(); 

       //read input into string 
       InputStream inputStream = urlConnection.getInputStream(); 
       StringBuffer buffer = new StringBuffer(); 
       if(inputStream == null){ 
        //nothing else to do in this case 
        return null; 
       } 
       reader = new BufferedReader(new InputStreamReader(inputStream)); 
       String line; 
       while((line = reader.readLine())!= null){ 
        buffer.append(line + "\n"); 
       } 

       if(buffer.length()==0){ 
        //nothing here, don't parse 
        return null; 
       } 

       posterJsonString = buffer.toString(); 
      } 
      catch(MalformedURLException e){ 
       e.printStackTrace(); 
      } 
      catch(IOException e){ 
       Log.e(LOG_TAG, "Error", e); 
       return 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{ 
       parseMovieJson();; 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void aVoid) { 
      super.onPostExecute(aVoid); 

      String[] asc = new String[movieModelList.size()]; 
      for(int i = 0; i < asc.length; i++){ 
       asc[i]=(getMovieModelList().get(i).getPoster_path()); 

      } 
      adapter.setImageArray(asc); 
      adapter.notifyDataSetChanged(); 
     } 
    } 
    public static List<MovieModel> getMovieModelList(){ 
     return movieModelList; 
    } 
    public static int getMovieModelListLength(){ 
     return movieModelListLength; 
    } 

} 

这里是错误代码:

FATAL EXCEPTION: main 
                      Process: tk.talcharnes.popularmovies, PID: 16847 
                      java.lang.RuntimeException: Unable to start activity ComponentInfo{tk.talcharnes.popularmovies/tk.talcharnes.popularmovies.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Spinner.setSelection(int)' on a null object reference 
                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2306) 
                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2366) 
                       at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3945) 
                       at android.app.ActivityThread.access$900(ActivityThread.java:149) 
                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1290) 
                       at android.os.Handler.dispatchMessage(Handler.java:102) 
                       at android.os.Looper.loop(Looper.java:135) 
                       at android.app.ActivityThread.main(ActivityThread.java:5290) 
                       at java.lang.reflect.Method.invoke(Native Method) 
                       at java.lang.reflect.Method.invoke(Method.java:372) 
                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908) 
                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703) 
                       Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Spinner.setSelection(int)' on a null object reference 
                       at tk.talcharnes.popularmovies.PostersFragment.onCreate(PostersFragment.java:115) 
                       at android.support.v4.app.Fragment.performCreate(Fragment.java:1939) 
                       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1029) 
                       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248) 
                       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230) 
                       at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:2037) 
                       at android.support.v4.app.FragmentController.dispatchCreate(FragmentController.java:154) 
                       at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:289) 
                       at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:61) 
                       at tk.talcharnes.popularmovies.MainActivity.onCreate(MainActivity.java:13) 
                       at android.app.Activity.performCreate(Activity.java:6020) 
                       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) 
                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259) 
                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2366)  
                       at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3945)  
                       at android.app.ActivityThread.access$900(ActivityThread.java:149)  
                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1290)  
                       at android.os.Handler.dispatchMessage(Handler.java:102)  
                       at android.os.Looper.loop(Looper.java:135)  
                       at android.app.ActivityThread.main(ActivityThread.java:5290)  
                       at java.lang.reflect.Method.invoke(Native Method)  
                       at java.lang.reflect.Method.invoke(Method.java:372)  
                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)  
                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)  
+0

当设备改变其方向活动正在重新创建那为什么片段失去它的状态。 在加载片段的活动中使用这些标志。 android:configChanges =“keyboardHidden | orientation | screenSize” –

回答

1

正如你所知道的整个Activity的方向变化后重建。您已使用onCreate方法编写代码,但当时spinner未初始化。

所以,你现在可以做的是

捆绑数据类型创建一个变量,使全球,并保存savedInstanceState该变量

if(savedInstanceState != null) { 
      this.myBundle = savedInstanceState; 
    } 

内。然后onCreateOptionsMenu检查this.myBundle是在致电spinner.setSelection之前是空的还是空的。您的代码如下所示,并在语句spinner.setAdapter(spinnerAdapter);后面写入以下代码行。

MenuItem item = menu.findItem(R.id.spinnerr); 
spinner = (Spinner) MenuItemCompat.getActionView(item); 

//rest of your codes 

spinner.setAdapter(spinnerAdapter); 

if(this.myBundle != null){ 
spinner.setSelection(myBundle.getInt("spinner", 0)); 
} 
+0

谢谢!这有助于旋转!虽然我只是注意到当我在动作栏中按下按钮时,它不会保存相同的问题。当我按下手机上的(物理)后退按钮,虽然它确实保存了旋转器的位置。有任何想法吗? –

+0

每次正常时调用savedInstanceState。如果你想防止这种情况,你可以覆盖onpause并清除捆绑。 –

+0

我确实希望它保存。我想说的是,我希望它能够保存我的位置,并在按菜单栏上的后退按钮时转到该位置。 –

1

还记得保存的实例包选择的位置上创建

if(savedInstanceState != null) { 
    savedSelection = savedInstanceState.getInt("spinner", 0); 
} 

,每当你的方向变化如此之贵的屏幕尺寸, 添加以下行后

MenuItem item = menu.findItem(R.id.spinnerr); 
spinner = (Spinner) MenuItemCompat.getActionView(item); 
spinner.setSelection(savedSelection); 
2

设置您的AndroidManifest.xml文件在您想要在旋转或尺寸更改时不要重新创建的活动中

android:configChanges="orientation|screenSize" 

这样您的活动将不会自动重新启动。 configChanges

列出配置更改该活动将处理本身:更多的相关信息

的Android见documentation。当运行时发生配置更改时,该活动默认关闭并重新启动,但使用此属性声明配置将会阻止活动重新启动。相反,该活动仍在运行,并调用onConfigurationChanged()方法。

+0

这只会允许像风景一样的模式吗?或者这个工作到底如何? –

+0

更新了我的答案...请检查 –

+1

这就像OP在问奶牛为什么不给奶,而你建议不要驯服奶牛。没有进攻兄弟。这也是一个更好的主意。 –