2016-09-02 10 views
5

Próbuję użyć fragmentu do otwarcia bazy danych, jednak po kliknięciu przycisku w celu rozpoczęcia wyszukiwania program nieoczekiwanie kończy się i wykazać błąd takiego:Próba wywołania metody wirtualnej "android.content.Context.getResources()" na odwołanym obiekcie o wartości zerowej

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference 
    at android.widget.Toast.<init>(Toast.java:102) 
    at android.widget.Toast.makeText(Toast.java:259) 
    at com.example.nkwpy.myapplication.MainFragment.query(MainFragment.java:176) 
    at com.example.nkwpy.myapplication.MainFragment.access$000(MainFragment.java:46) 
    at com.example.nkwpy.myapplication.MainFragment$queryListener.onClick(MainFragment.java:161) 
    at android.view.View.performClick(View.java:5207) 
    at android.view.View$PerformClick.run(View.java:21177) 
    at android.os.Handler.handleCallback(Handler.java:739) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5458) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628) 

MainFragment:

package com.example.nkwpy.myapplication; 
import android.content.Context; 
import android.net.Uri; 
import android.os.Bundle; 
import android.app.Fragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.widget.EditText; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.view.View.OnClickListener; 
import android.widget.Toast; 



/** 
* A simple {@link Fragment} subclass. 
* Activities that contain this fragment must implement the 
* {@link MainFragment.OnFragmentInteractionListener} interface 
* to handle interaction events. 
* Use the {@link MainFragment#newInstance} factory method to 
* create an instance of this fragment. 
*/ 
public class MainFragment extends Fragment { 
    // TODO: Rename parameter arguments, choose names that match 
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER 
    private static final String ARG_PARAM1 = "param1"; 
    private static final String ARG_PARAM2 = "param2"; 

    MainActivity parent=(MainActivity) getActivity(); 
    SQLiteDatabase test; 
    DBManager dbHelper; 


    // TODO: Rename and change types of parameters 
    private String mParam1; 
    private String mParam2; 

    private EditText N; 
    private EditText Z; 
    private EditText R_A; 
    private Button queryBtn; 

    private OnFragmentInteractionListener mListener; 

    public MainFragment() { 
     // Required empty public constructor 
    } 

    /** 
    * Use this factory method to create a new instance of 
    * this fragment using the provided parameters. 
    * 
    * @param param1 Parameter 1. 
    * @param param2 Parameter 2. 
    * @return A new instance of fragment MainFragment. 
    */ 
    // TODO: Rename and change types and number of parameters 
    public static MainFragment newInstance(String param1, String param2) { 
     MainFragment fragment = new MainFragment(); 
     Bundle args = new Bundle(); 
     args.putString(ARG_PARAM1, param1); 
     args.putString(ARG_PARAM2, param2); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     if (getArguments() != null) { 
      mParam1 = getArguments().getString(ARG_PARAM1); 
      mParam2 = getArguments().getString(ARG_PARAM2); 
     } 


    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     View view =inflater.inflate(R.layout.fragment_main, container, false); 
     N=(EditText)view.findViewById(R.id.neuton); 
     Z=(EditText)view.findViewById(R.id.proton); 
     queryBtn = (Button)view.findViewById(R.id.query); 
     queryBtn.setOnClickListener(new queryListener()); 
     R_A=(EditText)view.findViewById(R.id.result); 


     dbHelper = new DBManager(getActivity()); 
     dbHelper.openDatabase(); 
     dbHelper.closeDatabase(); 
     return view; 
    } 

    // TODO: Rename method, update argument and hook method into UI event 
    public void onButtonPressed(Uri uri) { 
     if (mListener != null) { 
      mListener.onFragmentInteraction(uri); 
     } 
    } 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     if (context instanceof OnFragmentInteractionListener) { 
      mListener = (OnFragmentInteractionListener) context; 
     } else { 
      throw new RuntimeException(context.toString() 
        + " must implement OnFragmentInteractionListener"); 
     } 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mListener = null; 
    } 

    /** 
    * This interface must be implemented by activities that contain this 
    * fragment to allow an interaction in this fragment to be communicated 
    * to the activity and potentially other fragments contained in that 
    * activity. 
    * <p/> 
    * See the Android Training lesson <a href= 
    * "http://developer.android.com/training/basics/fragments/communicating.html" 
    * >Communicating with Other Fragments</a> for more information. 
    */ 
    public interface OnFragmentInteractionListener { 
     // TODO: Update argument type and name 
     void onFragmentInteraction(Uri uri); 
    } 

    class queryListener implements OnClickListener{ 

     @Override 
     public void onClick(View v) { 
      // 
      query(); 
      test.close(); 
     } 
    } 
    private void query() { 

     try { 
      String string1 = N.getText().toString(); 
      String string2 = Z.getText().toString(); 
      String sql = "select * from sly4 where N=" + string1 + " and Z=" + string2; 
      Cursor cursor =test.rawQuery(sql, null); 
      cursor.moveToFirst(); 
      String r = cursor.getString(cursor.getColumnIndex("value")); 
      R_A.setText(r); 
     } catch (Exception e) { 
      Toast.makeText(parent, "Please check the number you entered", Toast.LENGTH_LONG).show(); 
     } 
    } 
} 

klasa DBManager:

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import android.content.Context; 
import android.database.sqlite.SQLiteDatabase; 
import android.os.Environment; 
import android.util.Log; 

public class DBManager { 
    private final int BUFFER_SIZE = 400000; 
    public static final String DB_NAME = "main.db"; 
    public static final String PACKAGE_NAME = "com.example.nkwpy.myapplication"; 
    public static final String DB_PATH = "/data" 
      + Environment.getDataDirectory().getAbsolutePath() + "/" 
      + PACKAGE_NAME; 

    private SQLiteDatabase database; 
    private Context context; 

    DBManager(Context context) { 
     this.context = context; 
    } 

    public void openDatabase() { 
     this.database = this.openDatabase(DB_PATH + "/" + DB_NAME); 
    } 

    private SQLiteDatabase openDatabase(String dbfile) { 
     try { 
      if (!(new File(dbfile).exists())) { 
       InputStream is = this.context.getResources().openRawResource(R.raw.main); 
       FileOutputStream fos = new FileOutputStream(dbfile); 
       byte[] buffer = new byte[BUFFER_SIZE]; 
       int count = 0; 
       while ((count = is.read(buffer)) > 0) { 
        fos.write(buffer, 0, count); 
       } 
       fos.close(); 
       is.close(); 
      } 
      SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile, 
        null); 
      return db; 
     } catch (FileNotFoundException e) { 
      Log.e("Database", "File not found"); 
      e.printStackTrace(); 
     } catch (IOException e) { 
      Log.e("Database", "IO exception"); 
      e.printStackTrace(); 
     } 
     return null; 
    } 
    public void closeDatabase() { 
     this.database.close(); 
    } 
} 

Przy okazji, użyłem kodu o DBManager w MainAcitivity i udało się. Po skopiowaniu kodu do fragmentu podobnego do powyższego, nie powiodło się. Jak mam to zrobić?

+0

Powołaj w której klasy iw której linii otrzymujesz ten błąd, dzięki czemu możemy sugerować. –

+0

Twój fragment powinien być odpowiedzialny tylko za działania związane z interfejsem użytkownika - zła praktyka polega na umieszczaniu tutaj dostępu do bazy danych. Zamiast tego spróbuj oddzwonić do działania, aby wykonać tę pracę za Ciebie. Czytaj więcej tutaj: http://simpledeveloper.com/how-to-communicate-between-fragments-and-activities/ –

Odpowiedz

12

Nie można wykonać MainActivity parent=(MainActivity) getActivity(); przed onAttach() i po onDetach().

Od tego czasu robisz w momencie tworzenia fragmentu. Metoda getActivity zawsze zwróci wartość null. Również w miarę możliwości nie staraj się zachować swojego numeru Activity w swoim Fragment. Może to spowodować wyciek pamięci, jeśli referencja nie zostanie poprawnie anulowana.

Użyj getActivity() lub getContext() wszędzie, gdzie to możliwe.

zmienić Toast jak poniżej:

Toast.makeText(getContext(), "Please check the number you entered", 
Toast.LENGTH_LONG).show(); 

lub

Toast.makeText(getActivity(), "Please check the number you entered", 
Toast.LENGTH_LONG).show(); 
+1

, który z nich działa? używając 'getActivity()' lub 'getContext()'? –

+0

oba nie działają dla mnie –

+0

@ GowthamanM Kiedy dzwonisz do dowolnej z powyższych metod? Czy wywołasz go po 'onDetach()' lub przed 'onAttach()'? –

Powiązane problemy