0

我遇到了Fragment和AsyncTask問題。問題是我正在創建一個Fragment來運行一個AsyncTask來運行一個計時器。該代碼獨立於我的所有其他代碼工作,並且我已經測試過無數次。問題是,當我把我的新代碼到我的應用程序,我在這一點上得到一個空指針:在啓動AsyncTask時獲取空指針異常,儘管看起來onCreate似乎包含所有變量

 public void onClick(View v) { 
    if(v==abbtn){ 
     aboutFragDialog(); 
    }else if(v==exbtn){ 
     finish(); 
    }else if(v==starest){ 
     if(mTaskFragment.isRunning()){ 
      mTaskFragment.cancel(); 
    } else { 

      mTaskFragment.start(); 
    }if(v==mgextbtn){ 
     mgcusd.dismiss(); 
    } 
    } 
} 

是推動錯誤的實際行是:if(mTaskFragment.isRunning()){。這個代碼鏈接到以下幾點:

 public void replaceFrag(){ 
    Bundle bundle = new Bundle(); 
    String tester2 = String.valueOf(startTime).toString(); 
    Log.i("VertygoEclypse - replaceFrag - Value for counter ", tester2); 
    if(tester2.matches("")){ 
     bundle.putString("SecValue", "15"); 
    } else { 
     bundle.putString("SecValue", tester2); 
    } 
    FragmentManager rfm = getSupportFragmentManager(); 
    if(mTaskFragment == null){ 
    TaskFragment mTaskFragment = new TaskFragment(); 
    mTaskFragment.setArguments(bundle); 
    rfm.beginTransaction().add(mTaskFragment, "task").commit(); 
    } else { 
     TaskFragment mTaskFragment = new TaskFragment(); 
     mTaskFragment = (TaskFragment) rfm.findFragmentByTag("task"); 
     mTaskFragment.setArguments(bundle); 
     rfm.beginTransaction().add(mTaskFragment, "task").commit(); 
    } 
} 

此方法從以下稱爲:

 @Override 
public void onItemSelected(AdapterView<?> parent, View view, int position, long l) { 
    switch(parent.getId()){ 
     case R.id.timerspinner: 
      TimerDataBaseHandler isdb = new TimerDataBaseHandler(getApplicationContext()); 
      SQLiteDatabase dbsec = isdb.getReadableDatabase(); 
      int tagposition = s.getSelectedItemPosition()+1; 
      isdb.getReadableDatabase(); 
      Cursor cc = dbsec.rawQuery("SELECT * FROM timers WHERE _id = "+tagposition, null); 
      if(cc.moveToFirst()){ 
       setTimer(Integer.parseInt(cc.getString(2))); 
       starest.setEnabled(true); 
       replaceFrag(); 
      } 
    } 
} 

上面的代碼就足夠了,在我的日誌TaskFragment活動我可以看到,我碰到送變量被視爲用作一個開始時間的倒計時,這是在這裏:

 @Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setRetainInstance(true); 
    bundle=getArguments(); 
    i = bundle.getString("SecValue"); 
    Log.i("VertygoEclypse - TaskFragment-onCreate", i); 
    counter=Integer.parseInt(i); 
    Log.i("VertygoEclypse - TaskFragment - onCreate", String.valueOf(counter).toString()); 
} 

這樣說,這個代碼單獨工作作爲一個獨立的和作品,並給出了預期的效果。問題是,當我將它與我的應用程序配合使用時,似乎雖然值移動到片段,但我無法啓動Asynctask。以下是我的代碼到目前爲止。

這是TaskFragment.class package com.vertygoeclypse.multitimer;

import android.app.Activity; 
    import android.os.AsyncTask; 
    import android.os.Bundle; 
    import android.os.SystemClock; 
    import android.support.v4.app.Fragment; 
    import android.util.Log; 

    public class TaskFragment extends Fragment { 
private static final String TAG = TaskFragment.class.getSimpleName(); 
String i; 
static int counter, validcounter; 
Bundle bundle; 
static interface TaskCallbacks { 
    public void onPreExecute(); 
    public void onProgressUpdate(int timer); 
    public void onCancelled(); 
    public void onPostExecute(); 
} 
private TaskCallbacks mCallbacks; 
private DummyTask mTask; 
private boolean mRunning; 
@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    if (!(activity instanceof TaskCallbacks)) { 
     throw new IllegalStateException("Activity must implement the TaskCallbacks interface."); 
    } 
    mCallbacks = (TaskCallbacks) activity; 
} 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setRetainInstance(true); 
    bundle=getArguments(); 
    i = bundle.getString("SecValue"); 
    Log.i("VertygoEclypse - TaskFragment-onCreate", i); 
    counter=Integer.parseInt(i); 
    Log.i("VertygoEclypse - TaskFragment - onCreate", String.valueOf(counter).toString()); 
} 
@Override 
public void onDestroy() { 
    super.onDestroy(); 
    cancel(); 
} 
public void start() { 
    if (!mRunning) { 
     Log.i("VertygoEclypse - TaskFragment - start", String.valueOf(counter).toString()); 
     mTask = new DummyTask(); 
     validcounter = counter; 
     Log.i("VertygoEclypse - TaskFragment - validcounter", String.valueOf(validcounter).toString()); 
     mTask.execute(); 
     mRunning = true; 
    } else{ 
     mTask.cancel(true); 
    } 
} 
public void cancel() { 
    if (mRunning) { 
     mTask.cancel(true); 
     mTask = null; 
     mRunning = false; 
    } 
} 
public boolean isRunning() { 
    return mRunning; 
} 
private class DummyTask extends AsyncTask<Void, Integer, Void> { 
    @Override 
    protected void onPreExecute() { 
     mCallbacks.onPreExecute(); 
     mRunning = true; 

     Log.i("Vertygo Eclypse - AsyncTask - onPreExecute", i); 
    } 
    @Override 
    protected Void doInBackground(Void... ignore) { 

     Log.i("Vertygo Eclypse - AsyncTask - onPreExecute", String.valueOf(validcounter).toString()); 
     do { 
      publishProgress(validcounter); 
      SystemClock.sleep(1000); 
      validcounter=validcounter-1; 
      if(isCancelled()){ 
       mTask.cancel(true); 
       break; 
      } 
     } while (validcounter>0); 
     return null; 
    } 
    @Override 
    protected void onProgressUpdate(Integer... timer) { 
     mCallbacks.onProgressUpdate(timer[0]); 
    } 
    @Override 
    protected void onCancelled() { 
     mCallbacks.onCancelled(); 
     mRunning = false; 
    } 
    @Override 
    protected void onPostExecute(Void ignore) { 
     mCallbacks.onPostExecute(); 
     mRunning = false; 
    } 
} 
    } 

在MainActivity是有點長,所以我希望沒有人會不高興,但我認爲,如果沒有看到代碼,一個正確的評估無法進行。

package com.vertygoeclypse.multitimer; 
    //-------------------------------------------------------------------------------------------------- 

    import android.app.Dialog; 
    import android.content.Context; 
    import android.database.Cursor; 
    import android.database.sqlite.SQLiteDatabase; 
    import android.graphics.Typeface; 
    import android.os.Bundle; 
    import android.os.CountDownTimer; 
    import android.os.Handler; 
    import android.os.Vibrator; 
    import android.support.v4.app.FragmentActivity; 
    import android.support.v4.app.FragmentManager; 
    import android.util.Log; 
    import android.view.Menu; 
    import android.view.MenuItem; 
    import android.view.View; 
    import android.view.View.OnClickListener; 
    import android.widget.AdapterView; 
    import android.widget.ArrayAdapter; 
    import android.widget.Button; 
    import android.widget.NumberPicker; 
    import android.widget.Spinner; 
    import android.widget.TextView; 

    import com.vertygoeclypse.multitimer.AddDialog.onSubmitListener; 
    import com.vertygoeclypse.multitimer.UpdateDialog.onSubmitUpdateListener; 

    import java.io.File; 
    import java.util.List; 
    import java.util.concurrent.TimeUnit; 

    import static android.widget.AdapterView.OnItemSelectedListener; 
    //-------------------------------------------------------------------------------------------------- 
    public class MainActivity extends FragmentActivity implements NumberPicker.OnValueChangeListener, OnClickListener, OnItemSelectedListener, onSubmitListener, onSubmitUpdateListener, TaskFragment.TaskCallbacks { 
    //-------------------------------------------------------------------------------------------------- 
Button abbtn, exbtn, starest, mgextbtn; 
TextView timeRemaining; 
Dialog mgcusd; 
Typeface tf; 
Spinner s; 
Vibrator v; 
protected CountDownTimer timerCountDownTimer; 
Handler timerHandler = new Handler(); 
public boolean timerHasStarted = false; 
protected int startTime=0; 
protected int val1, val2, val3, val4, temp1, upposval, validcounter; 
protected String tagval1, temp2, uptagval, uptimeval; 
boolean savechkbx=true; 
File mydb ; 
public static Context PACKAGE_NAME; 
private static final String TIME_COUNT = "time_count"; 
private TaskFragment mTaskFragment; 
    //-------------------------------------------------------------------------------------------------- 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    //-------------------------------------------------------------------------------------------------- 
    PACKAGE_NAME = getApplicationContext(); 
    TimerDataBaseHandler db = new TimerDataBaseHandler(getApplicationContext()); 
    mydb = new File("/data/data/com.vertygoeclypse.multitimer/databases/TimerManager"); 
    if(mydb.exists()){ 

    } else { 
     db.addTimer(new TimerClass("Lipton", "180")); 
    } 
    //-------------------------------------------------------------------------------------------------- 
    abbtn = (Button) findViewById(R.id.aboutbtn); 
    exbtn = (Button) findViewById(R.id.exitbtn); 
    starest = (Button) findViewById(R.id.startresetbtn); 
    timeRemaining = (TextView) findViewById(R.id.timeremainingview); 
    s = (Spinner)findViewById(R.id.timerspinner); 
    tf = Typeface.createFromAsset(getAssets(),"digital7.ttf"); 
    v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); 
    //-------------------------------------------------------------------------------------------------- 
    abbtn.setOnClickListener(this); 
    exbtn.setOnClickListener(this); 
    starest.setOnClickListener(this); 
    s.setOnItemSelectedListener(this); 
    //-------------------------------------------------------------------------------------------------- 
    if(startTime==0){ 
     starest.setEnabled(false); 
    }else if(startTime>0){ 
     starest.setEnabled(true); 
     starest.setTextColor(getResources().getColor(android.R.color.primary_text_light)); 
    } 
    LoadSpinnerData(); 

    if (savedInstanceState != null) { 
     timeRemaining.setTypeface(tf); 
     timeRemaining.setText(savedInstanceState.getString(TIME_COUNT)); 
    } 
} 
@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putString(TIME_COUNT, timeRemaining.getText().toString()); 
} 
    //-------------------------------------------------------------------------------------------------- 
public void LoadSpinnerData(){ 
    TimerDataBaseHandler tdb = new TimerDataBaseHandler(getApplicationContext()); 
    List<String> timerlabels = tdb.fetchAllTimers(); 
    ArrayAdapter<String> dataAdapter; 
    dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, timerlabels); 
    dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    s.setAdapter(dataAdapter); 
} 
public void mgLoadSpinnerData(){ 
    TimerDataBaseHandler updb = new TimerDataBaseHandler(getApplicationContext()); 
    List<String> updatetimers = updb.fetchAllTimers(); 
    ArrayAdapter<String> dataAdapter; 
    dataAdapter = new ArrayAdapter<String>(this, R.layout.customer_colored_spinner_item, updatetimers); 
    dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    UpdateDialog.mgs.setAdapter(dataAdapter); 
} 
    //-------------------------------------------------------------------------------------------------- 
@Override 
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {} 
    //-------------------------------------------------------------------------------------------------- 
public static String getDurationBreakdown(long secondstobreak) { 
    if(secondstobreak < 0) 
    { 
     throw new IllegalArgumentException("Duration must be greater than zero!"); 
    } 
    long hours = TimeUnit.MILLISECONDS.toHours(secondstobreak); 
    secondstobreak-=TimeUnit.HOURS.toMillis(hours); 
    long minutes = TimeUnit.MILLISECONDS.toMinutes(secondstobreak); 
    secondstobreak-=TimeUnit.MINUTES.toMillis(minutes); 
    long seconds = TimeUnit.MILLISECONDS.toSeconds(secondstobreak); 
    secondstobreak-=TimeUnit.SECONDS.toMillis(seconds); 
    StringBuilder sb = new StringBuilder(64); 
    if(hours<10){ 
     sb.append("0"+hours); 
    }else { 
    sb.append(hours); 
    } 
    sb.append(" : "); 
    if(minutes<10){ 
     sb.append("0"+minutes); 
    }else{ 
    sb.append(minutes); 
    } 
    sb.append(" : "); 
    if(seconds<10){ 
     sb.append("0"+seconds); 
    } else { 
     sb.append(seconds); 
    } 
    sb.append(" remaining"); 
    return (sb.toString()); 
} 
    //-------------------------------------------------------------------------------------------------- 
public void setTimer(int minutes) { 
    if(timerHasStarted) 
     return; 
    startTime = minutes; 
    if(startTime < 1) 
     startTime = 1; 
    long val6 = (long)startTime*1000; 
    String ststring = getDurationBreakdown(val6); 
    timeRemaining.setText(ststring); 
    timeRemaining.setTypeface(tf); 
} 
    //-------------------------------------------------------------------------------------------------- 
public void onClick(View v) { 
    if(v==abbtn){ 
     aboutFragDialog(); 
    }else if(v==exbtn){ 
     finish(); 
    }else if(v==starest){ 
     if(mTaskFragment.isRunning()){ 
      mTaskFragment.cancel(); 
    } else { 

      mTaskFragment.start(); 
    }if(v==mgextbtn){ 
     mgcusd.dismiss(); 
    } 
    } 
} 
    //-------------------------------------------------------------------------------------------------- 
    //-------------------------------------------------------------------------------------------------- 
public void aboutFragDialog(){ 
    AboutDialog abtdialog = new AboutDialog(); 
    abtdialog.show(getFragmentManager(),""); 
} 
    //-------------------------------------------------------------------------------------------------- 
    //-------------------------------------------------------------------------------------------------- 
public void addFragDialog(){ 
    AddDialog dialog = new AddDialog(); 
    dialog.minListener = MainActivity.this; 
    dialog.secListener = MainActivity.this; 
    dialog.tagListener = MainActivity.this; 
    dialog.chkbxListener = MainActivity.this; 
    dialog.show(getFragmentManager(),""); 
} 
    //-------------------------------------------------------------------------------------------------- 
public void workOutResults(){ 
val3 = (val1*60)*1000; 
val4 = val2*1000; 
setTimer((val3+val4)/1000); 
temp1 = startTime; 
temp2 = String.valueOf(temp1); 
starest.setEnabled(true); 
if(tagval1.isEmpty()){ 
    savechkbx=false; 
} 
if(savechkbx){ 
    TimerDataBaseHandler tdb = new TimerDataBaseHandler(getApplicationContext()); 
    tdb.addTimer(new TimerClass(tagval1, temp2)); 
} 
LoadSpinnerData(); 
    } 
    //-------------------------------------------------------------------------------------------------- 
public void updateFragDialog(){ 
    TimerDataBaseHandler db = new TimerDataBaseHandler(getApplicationContext()); 
    UpdateDialog updialog = new UpdateDialog(); 
    updialog.uptgListener = MainActivity.this; 
    updialog.uptimListener = MainActivity.this; 
    updialog.upposListener = MainActivity.this; 
    updialog.show(getFragmentManager(),""); 
} 
    //-------------------------------------------------------------------------------------------------- 
public void updateTimerresults(){ 
    TimerDataBaseHandler mgdb = new TimerDataBaseHandler(getApplicationContext()); 
    SQLiteDatabase mgdb1 = mgdb.getReadableDatabase(); 
    if(mgdb1!=null){ 
     Cursor mgc = mgdb1.rawQuery("SELECT * FROM timers where _id = "+ upposval, null); 
     if(mgc.moveToFirst()){ 
      mgdb.updateTimer(new TimerClass(upposval, uptagval, uptimeval)); 
     } 
    } 
    mgLoadSpinnerData(); 
} 
    //-------------------------------------------------------------------------------------------------- 
public void deleteaTimer(){ 
    TimerDataBaseHandler deldb = new TimerDataBaseHandler(getApplicationContext()); 
    SQLiteDatabase deldb2 = deldb.getReadableDatabase(); 
    int tagposition1 = s.getSelectedItemPosition()+1; 
    String tagposval = String.valueOf(tagposition1); 
    if (deldb2 != null) { 
     Cursor cccc = deldb2.rawQuery("SELECT * FROM timers where _id = " + tagposval, null); 
     if(cccc.moveToFirst()){ 
      int val0 = cccc.getInt(0); 
      String val1= cccc.getString(1); 
      String val2 = cccc.getString(2); 
      deldb.deleteTimer(new TimerClass(val0, val1, val2)); 
     } 
    } 
    LoadSpinnerData(); 
} 
    //-------------------------------------------------------------------------------------------------- 
    //-------------------------------------------------------------------------------------------------- 
@Override 
public void onItemSelected(AdapterView<?> parent, View view, int position, long l) { 
    switch(parent.getId()){ 
     case R.id.timerspinner: 
      TimerDataBaseHandler isdb = new TimerDataBaseHandler(getApplicationContext()); 
      SQLiteDatabase dbsec = isdb.getReadableDatabase(); 
      int tagposition = s.getSelectedItemPosition()+1; 
      isdb.getReadableDatabase(); 
      Cursor cc = dbsec.rawQuery("SELECT * FROM timers WHERE _id = "+tagposition, null); 
      if(cc.moveToFirst()){ 
       setTimer(Integer.parseInt(cc.getString(2))); 
       starest.setEnabled(true); 
       replaceFrag(); 
      } 
    } 
} 
    //-------------------------------------------------------------------------------------------------- 
@Override 
public void onNothingSelected(AdapterView<?> adapterView) { } 
    //-------------------------------------------------------------------------------------------------- 
@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
getMenuInflater().inflate(R.menu.main, menu); 
return true; 
    } 
    //-------------------------------------------------------------------------------------------------- 
@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    int id = item.getItemId(); 
        if (id == R.id.action_new) { 
         addFragDialog(); 
         return true; 
    }else   if (id == R.id.action_discard) { 
         deleteaTimer(); 
         return true; 
    }else   if (id == R.id.action_edit) { 
         updateFragDialog(); 
         return true; 
    } 
    return super.onOptionsItemSelected(item); 
} 
    //-------------------------------------------------------------------------------------------------- 
public void setOSMinListener(String arg){ 
    val1 = Integer.parseInt(arg); 
} 
public void setOSSecListener(String arg){ 
    val2 = Integer.parseInt(arg); 
} 
public void setOSTagListener(String arg){ 
    tagval1 = arg; 
} 
public void setOSCkbListener(String arg){ 
    savechkbx = Boolean.parseBoolean(arg); 
} 
public void updateOStagListener(String arg){ 
    uptagval = arg; 
} 
public void updateOSTimeListener(String arg) { 
    uptimeval = arg; 
} 
public void updateOSPosListener(String arg){ 
    upposval = Integer.parseInt(arg); 
} 

public void replaceFrag(){ 
    Bundle bundle = new Bundle(); 
    String tester2 = String.valueOf(startTime).toString(); 
    Log.i("VertygoEclypse - replaceFrag - Value for counter ", tester2); 
    if(tester2.matches("")){ 
     bundle.putString("SecValue", "15"); 
    } else { 
     bundle.putString("SecValue", tester2); 
    } 
    FragmentManager rfm = getSupportFragmentManager(); 
    if(mTaskFragment == null){ 
    TaskFragment mTaskFragment = new TaskFragment(); 
    mTaskFragment.setArguments(bundle); 
    rfm.beginTransaction().add(mTaskFragment, "task").commit(); 
    } else { 
     TaskFragment mTaskFragment = new TaskFragment(); 
     mTaskFragment = (TaskFragment) rfm.findFragmentByTag("task"); 
     mTaskFragment.setArguments(bundle); 
     rfm.beginTransaction().add(mTaskFragment, "task").commit(); 
    } 
} 
public void initialfrag(){ 
    Log.i("VertygoEclypse - InitialFrag ","Called"); 
    Bundle bundl = new Bundle(); 
    String tester = timeRemaining.getText().toString(); 
    if(tester.matches("")){ 
     bundl.putString("SecValue", "15"); 
    } else{ 
     bundl.putString("SecValue", String.valueOf(startTime).toString()); 
    } 
    FragmentManager fm = getSupportFragmentManager(); 
    TaskFragment mTaskFragment = new TaskFragment(); 
    mTaskFragment = (TaskFragment) fm.findFragmentByTag("task"); 
    if (mTaskFragment == null) { 
     mTaskFragment = new TaskFragment(); 
     mTaskFragment.setArguments(bundl); 
     fm.beginTransaction().add(mTaskFragment, "task").commit(); 
    } 
} 
@Override 
public void onPreExecute() { 
    starest.setText("cancel"); 
} 
@Override 
public void onProgressUpdate(int timer) { 
    setTimer(timer); 
} 
@Override 
public void onCancelled() { 
    starest.setText("Start"); 
    timeRemaining.setTypeface(tf); 
    timeRemaining.setText("0 seconds"); 
    mTaskFragment.cancel(); 
    replaceFrag(); 
} 
@Override 
public void onPostExecute() { 
    starest.setText("Start"); 
    timeRemaining.setTypeface(tf); 
    timeRemaining.setText("Completed"); 
    mTaskFragment.cancel(); 
    replaceFrag(); 
} 
    } 

任何幫助,在此,將不勝感激。

問候

cchinchoy

回答

1

再一次它似乎我已經回答了我的問題,與試錯的代碼的2固體天,事實上,我從另一個問題我貼的想法。 mRunning值需要是靜態的,以便它對於Activity和Fragment中的任務是相同的。這種情況下,將代碼private boolean mRunning;更改爲這個private static boolean mRunning;可以讓代碼現在按照它應該的方式啓動。作爲android編程的新手,我仍然習慣於需要諸如public,private,static和sorts這樣的限定符。我希望這會幫助像我這樣的其他新手,並幫助節省傾倒代碼的時間來嘗試找到問題。

再次感謝探空板。

問候

cchinchoy