2017-07-03 8 views
0

私のコードには空港とフライト(出発と到着)の2つの基本クラスがあります。空港は、到着する飛行オブジェクトのリストと出発飛行オブジェクトのリストで構成されています。 私の主な活動では、私は空港オブジェクトのリストを保持し、それらをリストビューで表します。リストビューオブジェクトに触れると、その空港オブジェクト(ActivityArrivalFlights)のすべての到着フライトを表示するための新しいアクティビティが開始されます。ここで空港オブジェクトをフィールドとして保持します。このアクティビティでは、同じ対象物に到着フライトを追加する機能があります。私はリストビューでもフライトを表し、アレイアダプター経由でフライトを追加します。他のアクティビティで作成されたオブジェクトは、メインアクティビティでは表示されません

問題はこれです。飛行オブジェクトが作成されて空港に追加されたとき、そのアクティビティが有効な限り存在します。 ActivityArrivalFlightsが破棄され、フォーカスがメインアクティビティにある場合、以前に追加された飛行オブジェクトはその空港にはありません。

ここに2つのアクティビティのコードがあります。私が何か間違っているか誰にでも教えてもらえますか?

public class MainActivity extends AppCompatActivity { 

    private static final int FILL_AIRPORT_REQUEST = 1; 
    private static final int EDIT_AIRPORT_REQUEST = 2; 

    static final String EDIT_AIRPORT_OBJECT_KEY = "editable"; 
    static final String EDIT_AIRPORT_POSITION_KEY = "position"; 
    static final String SELECTED_AIRPORT_KEY = "selectedAirport"; 
    static final String ALL_FLIGHTS_LIST_KEY = "allFlights"; 

    private static final String AIRPORTS_STATE = "airportsState"; 

    private Button btnAddAirport; 
    private ListView lvAirports; 

    private ArrayList<Airport> airports; 
    private ArrayAdapter<Airport> airportArrayAdapter; 

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

     btnAddAirport = (Button) findViewById(R.id.btnAddAirport); 
     lvAirports = (ListView) findViewById(R.id.lwAirports); 
     btnAddAirport.setOnClickListener(this::onButtonAddAirportClick); 
     lvAirports.setOnItemClickListener(this::onListViewItemClicked); 


     if (savedInstanceState != null) 
      airports = savedInstanceState.getParcelableArrayList(AIRPORTS_STATE); 
     else 
      airports = new ArrayList<>(); 

     airportArrayAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, airports); 
     lvAirports.setAdapter(airportArrayAdapter); 
     lvAirports.invalidateViews(); 
     registerForContextMenu(lvAirports); 
     if(savedInstanceState == null) 
      addCodeForTesting(); 
    } 

    private void addCodeForTesting() { 
     /* TEMPORARY CODE FOR TESTING*/ 
     Airport munich = new Airport("MunichAirport", "Munich", "MU", 1234); 
     Airport skopje = new Airport("Aleksandar Veliki", "Skopje", "SK", 4321); 
     skopje.addArrivalFlight(munich, new Date(), new Date()); 
     airportArrayAdapter.add(skopje); 
     airportArrayAdapter.add(munich); 
    } 

    private void onButtonAddAirportClick(View view){ 
     startActivityForResult(new Intent(this, ActivityAddAirport.class), FILL_AIRPORT_REQUEST); 
    } 

    private void onListViewItemClicked(AdapterView parent, View view, int position, long id){ 
     Airport airport = airports.get(position); 
     showFlightsActivity(airport); 
    } 

    private void showFlightsActivity(Airport airport) { 
     Intent intent = new Intent(this, ActivityArrivalFlights.class); 
     ArrayList<Airport> filteredList = filterAirports(airports, airport); 
     intent.putExtra(SELECTED_AIRPORT_KEY, airport); 
     intent.putParcelableArrayListExtra(ALL_FLIGHTS_LIST_KEY, filteredList); 
     startActivity(intent); 
    } 

    private static ArrayList<Airport> filterAirports(List<Airport> original, Airport except){ 
     ArrayList<Airport> filtered = new ArrayList<>(); 
     for (Airport airport : original) { 
      if(!airport.equals(except)) 
       filtered.add(airport); 
     } 
     return filtered; 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data){ 
     if(requestCode == FILL_AIRPORT_REQUEST){ 
      if(resultCode == RESULT_OK){ 
       Airport airport = data.getParcelableExtra(ActivityAddAirport.AIRPORT_OBJECT_KEY); 
       airportArrayAdapter.add(airport); 
      } 
     } 
     else if(requestCode == EDIT_AIRPORT_REQUEST){ 
      if(resultCode == RESULT_OK){ 
       Airport editedAirport = data.getParcelableExtra(ActivityAddAirport.AIRPORT_OBJECT_KEY); 
       int airportPosition = data.getIntExtra(ActivityAddAirport.AIRPORT_POSITION, 0); 
       airports.remove(airportPosition); 
       airports.add(airportPosition, editedAirport); 
       airportArrayAdapter.notifyDataSetChanged(); 
       lvAirports.invalidateViews(); 
       Toast.makeText(this, "Airport changed", Toast.LENGTH_LONG).show(); 
      } 
     } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putParcelableArrayList(AIRPORTS_STATE, airports); 
    } 

    @Override 
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { 
     super.onCreateContextMenu(menu, v, menuInfo); 
     getMenuInflater().inflate(R.menu.main_menu_context_menu, menu); 
    } 

    @Override 
    public boolean onContextItemSelected(MenuItem item) { 
     if(item.getItemId() == R.id.context_edit) { 
      AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); 
      editListViewItem(info.position); 
      return true; 
     } 
     else if (item.getItemId() == R.id.context_delete){ 
      AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); 
      deleteListViewItem(info.position); 
      return true; 
     } 
     return super.onContextItemSelected(item); 
    } 

    private void editListViewItem(int position) { 
     Intent editIntent = new Intent(this, ActivityAddAirport.class); 
     Airport changingAirport = (Airport) lvAirports.getItemAtPosition(position); 
     editIntent.putExtra(EDIT_AIRPORT_OBJECT_KEY, changingAirport); 
     editIntent.putExtra(EDIT_AIRPORT_POSITION_KEY, position); 
     startActivityForResult(editIntent, EDIT_AIRPORT_REQUEST); 
    } 

    private void deleteListViewItem(int position){ 
     airportArrayAdapter.remove(airports.get(position)); 
    } 
} 

public class ActivityArrivalFlights extends AppCompatActivity { 

    private static final int FILL_ARRIVAL_FLIGHT_REQUEST = 1; 

    static final String AIRPORT_THIS_KEY = "thisAirport"; 
    static final String ALL_AIRPORTS_EXCEPT_THIS_KEY = "allExceptThis"; 

    private Airport airport; 
    private ArrayList<Airport> allAirportsExceptThis; 

    private ArrayAdapter<ArrivalFlight> lvArrivalsAdapter; 


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

     FloatingActionButton fabAddArrival = (FloatingActionButton) findViewById(R.id.fabAddArrival); 
     fabAddArrival.setOnClickListener(this::onFabAddArrivalClick); 

     Intent intent = getIntent(); 
     airport = intent.getParcelableExtra(MainActivity.SELECTED_AIRPORT_KEY); 
     allAirportsExceptThis = intent.getParcelableArrayListExtra(MainActivity.ALL_FLIGHTS_LIST_KEY); 

     setUpListView(); 
    } 

    private void setUpListView(){ 
     ListView lvArrivals = (ListView) findViewById(R.id.lvArrivals); 
     lvArrivalsAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, airport.getArrivals()); 
     lvArrivals.setAdapter(lvArrivalsAdapter); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.menu_choose_flights, menu); 
     return super.onCreateOptionsMenu(menu); 
    } 

    @Override 
    public boolean onPrepareOptionsMenu(Menu menu) { 
     MenuItem arrivals = menu.findItem(R.id.arrivals); 
     MenuItem departures = menu.findItem(R.id.departures); 
     if (arrivals.isEnabled()) 
      arrivals.setEnabled(false); 
     if (!departures.isEnabled()) 
      departures.setEnabled(true); 
     return super.onPrepareOptionsMenu(menu); 
    } 



    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     if(item.getItemId() == R.id.departures){ 
      Intent intent = new Intent(this, ActivityDepartureFlights.class); 
      intent.putExtra(MainActivity.SELECTED_AIRPORT_KEY, airport); 
      startActivity(intent); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    private void onFabAddArrivalClick(View view){ 
     Intent intent = new Intent(this, ActivityAddArrivalFlight.class); 
     intent.putExtra(AIRPORT_THIS_KEY, airport); 
     intent.putParcelableArrayListExtra(ALL_AIRPORTS_EXCEPT_THIS_KEY, allAirportsExceptThis); 
     startActivityForResult(intent, FILL_ARRIVAL_FLIGHT_REQUEST); 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if(requestCode == FILL_ARRIVAL_FLIGHT_REQUEST){ 
      if(resultCode == RESULT_OK){ 
       ArrivalFlight flight = data.getParcelableExtra(ActivityAddArrivalFlight.FILLED_FLIGHT_ENTRY); 
       lvArrivalsAdapter.add(flight); 
       Toast.makeText(this, "Flight added!\n" + airport.getArrivals().size(), Toast.LENGTH_SHORT).show(); 
      } 
     } 
    } 
} 

答えて

0

私はActivityArrivalFlightsの破壊時にMainActivityは新しいフライトに更新されますない理由を見ません。 MainActivityで

あなたはあなたのような何かをする必要がある追加された飛行を返すあなたのケースでは、MainActivityにデータを返すために (ActivityArrivalFlightsから)MainActivityにどんな結果を返すされていない

@Override 
public void onBackPressed() { 

    // You can wrap this with: If(newFlightsAdded()) { ... }: 
    Intent output = new Intent(); 
    output.putExtra("NEW_FILGHT_DATA", newFlight); 
    setResult(RESULT_OK, output); 
    finish(); 
} 

私はあなたにマイルを推測全体のコンセプトです:ActivityArrivalFlightsから

final int NEW_FLIGHT_RESULT = 5; // Just an identifier number/what ever you want; 

// Start ActivityArrivalFlights for result (which you are not doing): 

private void showFlightsActivity(Airport airport) { 
    Intent intent = new Intent(this, ActivityArrivalFlights.class); 
    ArrayList<Airport> filteredList = filterAirports(airports, airport); 
    intent.putExtra(SELECTED_AIRPORT_KEY, airport); 
    intent.putParcelableArrayListExtra(ALL_FLIGHTS_LIST_KEY, filteredList); 
    startActivityForResult(intent, NEW_FLIGHT_RESULT); // Here start for result 
} 


@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data){ 
    if(requestCode == NEW_FLIGHT_RESULT){ 
     if(resultCode == RESULT_OK) { 
      Flight f = data.getParcelableExtra("NEW_FILGHT_DATA"); 
      // Here add the new flight to the airport object you are maintaining !!! 
     } 
    } 

ssed、私のコードは素早く汚れていますので、それをきれいにして使いましょう。

注意!!! :インテントを使用してアクティビティ間でオブジェクトを渡す(intent.putExtra(...)は、同じオブジェクトではなくオブジェクトのコピーを渡します)。

+0

ありがとうございますが、これは私が探していたものではありません。私はこの概念を知っています。 アイデアは空港オブジェクトの参照をActivityArrivalFlightsアクティビティに渡すことです。同じオブジェクトに加えられた変更はどこでも見ることができます。なぜなら、同じオブジェクトなので、私はそれを参照するだけです。私が考えさせたのは、これらの変更が主な活動では見えない理由です。 –

+0

@DraganApostolski intent.putExtraは、オブジェクトのコピーを渡しますが、オブジェクト自体ではなく、intent.getExtraによって受け取られたオブジェクトの何かを変更すると、オブジェクトコピーが変更されます。 airportをstatic(テストのみ)にし、putExtraで渡されたオブジェクトを(MainActivityで定義されている)元の静的オブジェクトと比較することで、オブジェクトが実際にコピーであるかどうかを確認し、airports == intentAirportsのようなrefを比較することができます。だから、上のように結果として新しい飛行機に戻ることが良い習慣です。 – Mercury

+0

私はこのメソッドに関するドキュメントを実際に読んでいない、私は本当にintent.putExtraが参照を渡すと思った。ありがとう、今私は解決策を見つけることを知っている。 –

関連する問題