5

Khi tôi cố gắng để có được một màu qua getResources().getColor(R.color.yellow) trong một Hoạt động bình thường tôi nhận được ngoại lệ này:NullPointerException tại android.content.ContextWrapper

07-12 11:58:38.019: E/AndroidRuntime(3233): FATAL EXCEPTION: main 
07-12 11:58:38.019: E/AndroidRuntime(3233): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.moveinblue.planner/com.moveinblue.planner.controller.plan.PlanDayScreen}: java.lang.NullPointerException 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1993) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2104) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.access$600(ActivityThread.java:132) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1157) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.os.Handler.dispatchMessage(Handler.java:99) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.os.Looper.loop(Looper.java:137) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.main(ActivityThread.java:4575) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at java.lang.reflect.Method.invokeNative(Native Method) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at java.lang.reflect.Method.invoke(Method.java:511) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at dalvik.system.NativeStart.main(Native Method) 
07-12 11:58:38.019: E/AndroidRuntime(3233): Caused by: java.lang.NullPointerException 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.content.ContextWrapper.getResources(ContextWrapper.java:81) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at com.moveinblue.planner.controller.plan.PlanDayScreen$4.<init>(PlanDayScreen.java:408) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at com.moveinblue.planner.controller.plan.PlanDayScreen.<init>(PlanDayScreen.java:406) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at java.lang.Class.newInstanceImpl(Native Method) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at java.lang.Class.newInstance(Class.java:1319) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.Instrumentation.newActivity(Instrumentation.java:1023) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1984) 
07-12 11:58:38.019: E/AndroidRuntime(3233):  ... 11 more 

Ai có thể cho tôi một số nhận thức muộn màng ở đây? Tôi hoàn toàn lạc mất.

Mã trong hoạt động:

package com.moveinblue.planner.controller.plan; 

import java.text.SimpleDateFormat; 
import java.util.BitSet; 
import java.util.Calendar; 

import android.app.AlertDialog; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.os.AsyncTask; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.AutoCompleteTextView; 
import android.widget.ImageButton; 
import android.widget.ImageView; 
import android.widget.ListView; 
import android.widget.Toast; 

import com.moveinblue.api.Login; 
import com.moveinblue.api.Planner; 
import com.moveinblue.api.UnauthorizedException; 
import com.moveinblue.api.io.InvalidURLException; 
import com.moveinblue.api.io.OfflineException; 
import com.moveinblue.api.model.ModelObject; 
import com.moveinblue.api.model.Plan; 
import com.moveinblue.api.model.time.Day; 
import com.moveinblue.api.model.time.ScheduledThingToDo; 
import com.moveinblue.api.model.time.ScheduledTime; 
import com.moveinblue.api.model.time.ScheduledTime.TimeOfDay; 
import com.moveinblue.planner.R; 
import com.moveinblue.planner.controller.GenericPlannerScreen; 
import com.moveinblue.planner.controller.thingtodo.ThingsToDoListScreen; 
import com.moveinblue.planner.controller.user.LoginScreen; 
import com.moveinblue.planner.ui.actionbar.ActionBar; 
import com.moveinblue.planner.ui.draganddroplist.DragListener; 
import com.moveinblue.planner.ui.draganddroplist.DragNDropListView; 
import com.moveinblue.planner.ui.draganddroplist.DropListener; 
import com.moveinblue.planner.ui.draganddroplist.RemoveListener; 
import com.moveinblue.planner.utils.CommonActionStorage; 
import com.moveinblue.planner.utils.CurrentItemsStorage; 
import com.moveinblue.planner.utils.adapter.DragNDropAdapter; 
import com.moveinblue.planner.utils.adapter.listeners.OnCheckListener; 

public class PlanDayScreen extends GenericPlannerScreen { 

DragNDropListView lista; 
AutoCompleteTextView actv; 
String[] dests; 
DragNDropAdapter adapter; 
private Boolean idDroppedOrDeleted = false; 
private BitSet checkedBoxes = new BitSet(); 
private boolean firstLoad = true; 
Day day; 
@SuppressWarnings("unused") 
private static final String LOG_TAG = PlanDayScreen.class 
     .getCanonicalName(); 

@Override 
public void load() { 
    setContentView(R.layout.plan_day_list); 
    setUpList(); 
    setUpBottomLayout(false); 
    lista.requestFocus(); 
} 

@Override 
protected void loadActionBar() { 
    Plan p = CurrentItemsStorage.currentPlan; 
    Calendar c = CurrentItemsStorage.currentDay; 
    ab = new ActionBar(this, ActionBar.TYPE_LIST); 
    String date = new SimpleDateFormat("MMM dd, yyyy").format(c.getTime()); 
    date = Character.toUpperCase(date.charAt(0)) + date.substring(1); 
    date = "(" + date + ")"; 
    String title; 

    title = (p != null) ? p.name + " " + date : "Draft plan"; 

    ab.setTitle(title); 
    ab.setBackAction(R.drawable.back, new OnClickListener() { 

     @Override 
     public void onClick(View arg0) { 
      Intent intent = new Intent(PlanDayScreen.this, 
        PlanTabsScreen.class); 
      intent.putExtra("tab", 2); 
      startActivity(intent); 
      overridePendingTransition(android.R.anim.slide_in_left, 
        android.R.anim.fade_out); 

     } 
    }); 
    CommonActionStorage.setUpActionBar(ab); 
} 

private void addNewTTD() { 
    if (getIntent().getBooleanExtra("schedule", false) && firstLoad) { 
     try { 
      Calendar c = CurrentItemsStorage.currentDay; 
      TimeOfDay tod = CurrentItemsStorage.currentTimeOfDaySelectedOption; 
      Planner.schedule(
        CurrentItemsStorage.getCurrentThingToDo().ttdId, 
        new ScheduledTime(c, tod)); 
     } catch (Exception ex) { 
      ex.getStackTrace(); 
     } 
    } 
    firstLoad = false; 
} 

/** 
* Sets up a bottom bar button 
* 
* @param id 
*   The bottom bar button id you want to set 
*/ 
private void setUpBottomButton(int id) { 
    ImageButton b = (ImageButton) findViewById(id); 
    switch (id) { 
    case R.id.buttonBottom1: 
     if (!areThereCheckedBoxes()) { 
      b.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // Add TTD to plan 
        Intent intent = new Intent(PlanDayScreen.this, 
          ThingsToDoListScreen.class); 
        startActivity(intent); 
       } 
      }); 
     } else { 
      b.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // Date 
       } 
      }); 
     } 
     break; 
    case R.id.buttonBottom2: 
     if (!areThereCheckedBoxes()) { 
      b.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // Map 
        if (day != null) { 
         CurrentItemsStorage.mapModelObjects = new ModelObject[0]; 
         CurrentItemsStorage.mapModelObjects[1] = day; 
         Intent intent = new Intent(PlanDayScreen.this, 
           PlanTabsScreen.class); 
         startActivity(intent); 
        } 

       } 
      }); 
     } else { 
      b.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // Confirm 
        new AlertDialog.Builder(PlanDayScreen.this) 
          .setIcon(android.R.drawable.ic_dialog_alert) 
          .setTitle(
            "Remove " + checkedCount() 
              + " things to do") 
          .setMessage(
            "Do you really wish to remove " 
              + checkedCount() 
              + " things to do from your plan?") 
          .setPositiveButton("Yes", 
            new DialogInterface.OnClickListener() { 

             @Override 
             public void onClick(
               DialogInterface dialog, 
               int which) { 
              // Remove 
              for (int i = 0; i < lista 
                .getCount(); i++) { 
               if (checkedBoxes.get(i)) { 
                // Get checked item 
                Object ttd = adapter 
                  .getItem(i); 
                if (ttd instanceof ScheduledThingToDo) { 
                 try { 
                  // Remove it 
                  ScheduledThingToDo tTD = (ScheduledThingToDo) ttd; 
                  Planner.unschedule(
                    tTD.ttdId, 
                    tTD.time); 
                 } catch (OfflineException ex) { 
                  Toast.makeText(
                    PlanDayScreen.this, 
                    getResources() 
                      .getString(
                        R.string.unschedule_error), 
                    Toast.LENGTH_SHORT) 
                    .show(); 
                 } catch (InvalidURLException e) { 
                 } 
                } 
               } 
              } 
              // Reset checkedBoxes and 
              // BottomLayout 
              checkedBoxes = new BitSet(); 
              setUpBottomLayout(false); 
              // Redraws the list 
              setUpList(); 
             } 
            }).setNegativeButton("No", null).show(); 
       } 
      }); 
     } 
     break; 
    case R.id.buttonBottom3: 
     b.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // Update 

      } 

     }); 
     break; 
    } 
} 

/** 
* Sets up the list 
*/ 
private void setUpList() { 
    lista = (DragNDropListView) findViewById(R.id.listViewAgenda); 
    new LoadList(); 
} 

/** 
* Counts the number of checked boxes 
* 
* @return the number of checked boxes 
*/ 
private int checkedCount() { 
    int x = 0; 
    for (int i = 0; i < checkedBoxes.length(); i++) { 
     x += checkedBoxes.get(i) ? 1 : 0; 
    } 
    return x; 
} 

/** 
* Changes the buttoms on the bottom action bar. If you pass true, you get 
* the "delete items" action bar. Else, you get the "add items" action bar. 
* 
* @param isAnythingMarked 
*   True if you want to delete items, false if you want to add 
*   them. 
*/ 
private void setUpBottomLayout(boolean isAnythingMarked) { 
    ImageButton b1 = (ImageButton) findViewById(R.id.buttonBottom1); 
    ImageButton b2 = (ImageButton) findViewById(R.id.buttonBottom2); 
    ImageButton b3 = (ImageButton) findViewById(R.id.buttonBottom3); 
    b1.setImageDrawable(getResources().getDrawable(
      isAnythingMarked ? R.drawable.action_plans 
        : R.drawable.action_add)); 
    b2.setImageDrawable(getResources().getDrawable(
      isAnythingMarked ? R.drawable.action_delete 
        : R.drawable.action_map)); 
    b3.setImageDrawable(getResources() 
      .getDrawable(R.drawable.action_reload)); 
    setUpBottomButton(R.id.buttonBottom1); 
    setUpBottomButton(R.id.buttonBottom2); 
    setUpBottomButton(R.id.buttonBottom3); 
} 

private boolean areThereCheckedBoxes() { 
    for (int i = 0; i < checkedBoxes.length(); i++) { 
     if (checkedBoxes.get(i)) { 
      return true; 
     } 
    } 
    return false; 
} 

public void clickControlRowHandler(View v) { 
    Intent intent = new Intent(PlanDayScreen.this, 
      ThingsToDoListScreen.class); 
    startActivity(intent); 
} 

/** 
* Drop Listener for the DragNDropListView 
*/ 
private DropListener mDropListener = new DropListener() { 
    public void onDrop(final int from, int to) { 
     if (to == 0) 
      to = 1; 
     // If initial position is the same as final position, do nothing. 
     if (to != from) { 
      if (adapter instanceof DragNDropAdapter) { 
       if (adapter.getItem(from) instanceof ScheduledThingToDo) { 
        new DropCall(from, to); 
        ((DragNDropAdapter) adapter).onDrop(from, to); 
       } 
      } 
     } 
    } 
}; 

public OnClickListener onClickSave = new OnClickListener() { 

    public void onClick(View v) { 
     try { 
      if (Login.isRegistered()) { 
       if (Planner.loadPlan().name == null) { 
        CurrentItemsStorage.shallGoAfterCreatePlan = PlanDayScreen.class; 
        if (idDroppedOrDeleted) { 
         manageListChanges(); 
        } 
        Intent intent = new Intent(PlanDayScreen.this, 
          SavePlanScreen.class); 
        startActivity(intent); 
        return; 
       } 
      } else { 
       CurrentItemsStorage.currentPlan = Planner.loadPlan(); 
       CurrentItemsStorage.shallGoAfterLogin = PlanDayScreen.class; 
       Intent intent = new Intent(PlanDayScreen.this, 
         LoginScreen.class); 
       startActivity(intent); 
      } 

     } catch (OfflineException e) { 
      Toast.makeText(PlanDayScreen.this, 
        getResources().getString(R.string.plan_error), 
        Toast.LENGTH_SHORT).show(); 
     } 
     if (idDroppedOrDeleted) { 
      manageListChanges(); 
     } 
    } 
}; 

/** 
* Unschedules every TTD, then schedules it again. 
*/ 
private void manageListChanges() { 

    for (int i = 0; i < adapter.getCount(); i++) { 
     Object item = adapter.getItem(i); 
     if (item instanceof ScheduledThingToDo) { 
      try { 
       ScheduledThingToDo scheduled = (ScheduledThingToDo) item; 
       Planner.unschedule(scheduled.getId(), scheduled.time); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
    int state = 0; 
    for (int it = 0; it < adapter.getCount(); it++) { 
     Object item = adapter.getItem(it); 
     TimeOfDay tod = TimeOfDay.morning; 
     if (item instanceof ScheduledThingToDo) { 
      switch (state) { 
      case 1: 
       tod = TimeOfDay.morning; 
       break; 
      case 2: 
       tod = TimeOfDay.afternoon; 
       break; 
      case 3: 
       tod = TimeOfDay.evening; 
       break; 
      } 
      try { 
       Planner.schedule(((ScheduledThingToDo) item).ttdId, 
         new ScheduledTime(CurrentItemsStorage.currentDay, 
           tod)); 
      } catch (OfflineException e) { 
       Toast.makeText(PlanDayScreen.this, "No connection", 
         Toast.LENGTH_SHORT).show(); 
      } 
     } else { 
      state++; 
     } 
    } 
} 

/** 
* RemoveListener for the DragNDropListView 
*/ 
private RemoveListener mRemoveListener = new RemoveListener() { 
    public void onRemove(int which) { 
     // ListAdapter adapter = getListAdapter(); 
     if (adapter instanceof DragNDropAdapter) { 
      ((DragNDropAdapter) adapter).onRemove(which); 
      lista.invalidateViews(); 
     } 
    } 
}; 

/** 
* DragListener for the DragNDropListView 
*/ 
private DragListener mDragListener = new DragListener() { 

    int backgroundColor = getResources().getColor(R.color.yellow); 
    int defaultBackgroundColor = getResources().getColor(R.color.blue_bg); 

    public void onDrag(int x, int y, ListView listView) { 
     // TODO Auto-generated method stub 
    } 

    public void onStartDrag(View itemView) { 
     itemView.setVisibility(View.INVISIBLE); 
     itemView.setBackgroundColor(backgroundColor); 
     ImageView iv = (ImageView) itemView.findViewById(R.id.imageView1); 
     if (iv != null) 
      iv.setVisibility(View.INVISIBLE); 
    } 

    public void onStopDrag(View itemView) { 
     itemView.setVisibility(View.VISIBLE); 
     itemView.setBackgroundColor(defaultBackgroundColor); 
     ImageView iv = (ImageView) itemView.findViewById(R.id.imageView1); 
     if (iv != null) 
      iv.setVisibility(View.VISIBLE); 
    } 
}; 

private class LoadList extends AsyncTask<Void, Void, Void> { 

    public LoadList() { 
     execute(); 
    } 

    @Override 
    protected void onPreExecute() { 
     String[] x = { "Loading..." }; 
     addNewTTD(); 
     ArrayAdapter<String> asdf = new ArrayAdapter<String>(
       PlanDayScreen.this, R.layout.add_more, x); 
     lista.setAdapter(asdf); 
    } 

    @Override 
    protected Void doInBackground(Void... arg0) { 
     ScheduledThingToDo[] ttds; 
     try { 
      try { 
       // Loads current day 
       day = Planner.loadDay(CurrentItemsStorage.currentDay); 
       ttds = day.ttds; 
      } catch (NullPointerException ex) { 
       // No current day: Loads today 
       Day day = Planner.loadDay(Calendar.getInstance()); 
       ttds = day.ttds; 
      } 
     } catch (OfflineException e) { 
      // Offline 
      Toast.makeText(PlanDayScreen.this, 
        getResources().getString(R.string.day_error), 
        Toast.LENGTH_SHORT).show(); 
      ttds = new ScheduledThingToDo[0]; 
     } catch (UnauthorizedException e) { 
      // Something strange happened 
      ttds = new ScheduledThingToDo[0]; 
     } catch (Exception e) { 
      // Something even more strange happened 
      ttds = new ScheduledThingToDo[0]; 
     } 

     adapter = new DragNDropAdapter(PlanDayScreen.this, 
       new int[] { R.layout.dragitemttd }, ttds); 

     adapter.setOnCheckListener(new OnCheckListener() { 

      @Override 
      public void onCheck(boolean isChecked, int position) { 
       checkedBoxes.set(position, isChecked); 
       setUpBottomLayout(areThereCheckedBoxes()); 
      } 
     }); 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     lista.setAdapter(adapter); 
     lista.setDropListener(mDropListener); 
     lista.setRemoveListener(mRemoveListener); 
     lista.setDragListener(mDragListener); 

    } 

} 

private class DropCall extends AsyncTask<Void, Void, Void> { 

    private int from, to; 

    public DropCall(int from, int to) { 
     this.from = from; 
     this.to = to; 
     execute(); 
     lista.invalidateViews(); 
    } 

    @Override 
    protected Void doInBackground(Void... arg0) { 
     changeScheduledTTD(from, to); 
     return null; 
    } 

    /** 
    * Unschedules a TTD and then re-schedules it in its proper place 
    * 
    * @param from 
    *   The position the TTD came from 
    * @param to 
    *   The position the TTD has been dragged to 
    */ 
    protected void changeScheduledTTD(int from, int to) { 
     ScheduledThingToDo currentTTD; 
     if (adapter.getItem(to) instanceof ScheduledThingToDo) 
      currentTTD = (ScheduledThingToDo) adapter.getItem(to); 
     else 
      return; 

     int indexMorning = 0; 
     int indexAfternoon = 0; 
     int indexEvening = 0; 
     Object item = null; 
     String currentTime = null; 
     // Gets the indexes for Morning, Afternoon and Evening 
     for (int i = 0; i < adapter.getCount(); i++) { 
      item = adapter.getItem(i); 
      if (item instanceof String) { 
       currentTime = (String) item; 
       if (currentTime.equals("MORNING")) { 
        indexMorning = i; 
       } 
       if (currentTime.equals("AFTERNOON")) { 
        indexAfternoon = i; 
       } 
       if (currentTime.equals("EVENING")) { 
        indexEvening = i; 
       } 
      } 
     } 

     TimeOfDay tod = null; 
     if (to >= indexEvening) { 
      tod = TimeOfDay.evening; 
     } else if (to >= indexAfternoon) { 
      tod = TimeOfDay.afternoon; 
     } else if (to >= indexMorning) { 
      tod = TimeOfDay.morning; 
     } 
     if (!currentTTD.time.getTimeOfDay().equals(tod)) { 

      try { 
       Planner.unschedule(currentTTD.ttdId, currentTTD.time); 
       Planner.schedule(currentTTD.ttdId, new ScheduledTime(
         CurrentItemsStorage.currentDay, tod)); 
      } catch (OfflineException e) { 
       e.printStackTrace(); 
      } 

     } 
    } 
} 
} 
+0

bạn có thể cung cấp cho chúng tôi mã hoạt động của bạn không? – AMerle

+0

Xong. Đó là một thời gian dài mặc dù ;-) ngoại lệ được ném vào dòng đầu tiên của mã trên khai báo mDragListener. – razielsarafan

+0

là bạn cố gắng chạy sau khi 'Làm sạch' dự án? –

Trả lời

7

bạn mDragListener là một biến thành viên. Tại thời điểm khởi tạo đối tượng Activity/instance có thể chưa sẵn sàng. Vì vậy, gọi getResource() của Hoạt động sẽ không thành công.

// inner class or normal class ... change scope if needed 
private class DragListener { 
    int color = 0; 
    public DragListener(Context context) { 
     color = context.getResource().getColor(R.color.yellow); 
    } 
} 

// activity 
private DragListener mDragListener; 
public void onCreate(...) { 
    mDragListener = new DragListener(this); 
    // more code 
} 
+0

Tùy chọn của tôi là gì? – razielsarafan

+0

Đặt DragListener làm lớp bên trong riêng tư với một hàm tạo có tham số ngữ cảnh. Bên trong hàm tạo khởi tạo các màu bằng cách sử dụng 'context.getResource()'. Sau đó, khởi tạo biến người nghe trong onCreate hoạt động của bạn. Các định nghĩa lớp ẩn danh như bạn không thể sử dụng lại được và chỉ có đủ trong các tình huống rất cụ thể. Tôi sẽ luôn cố gắng làm cho các lớp học có thể tái sử dụng được. – WarrenFaith

-4
int backgroundColor = Color.YELLOW; 

thay vì

int backgroundColor = getResources().getColor(R.color.yellow); 
+3

Ai nói rằng 'R.color.yellow == Color.YELLOW'? – WarrenFaith

+1

R.color.yellow KHÔNG phải là màu.Yellow. Thậm chí không gần. – razielsarafan

+0

Đây không phải là giải pháp cho vấn đề về OP. Vấn đề của anh ta là gọi hàm getResources() trước khi bối cảnh được khởi tạo. –

Các vấn đề liên quan