2017-07-03 64 views
0

我的代码中有两个基本类:机场和航班(出发和到达)。机场由到达航班对象列表和出发航班对象列表组成。 在我的主要活动中,我拥有一个机场对象列表并在列表视图中表示它们。通过触摸列表视图对象,我将启动一个新的活动,以显示该机场对象(ActivityArrivalFlights)的所有到达航班,其中我将机场对象作为字段保存。在这个活动中,有一个将到达航班添加到同一个对象的功能。我还在列表视图中显示航班,并通过数组适配器添加航班。在其他活动中创建的对象在主要活动中不可见

问题是这样的:当一个飞行对象被创建并添加到机场时,只要活动存在,它就在那里。当ActivityArrivalFlights被销毁并且焦点在主要活动上时,先前添加的飞行对象不在该机场中。

下面是两个活动的代码。任何人都可以告诉我,如果我做错了什么?

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(从ActivityArrivalFlights) 为了将数据恢复到MainActivity,你的情况恢复已添加你需要做的是这样的飞行:

在MainActivity:

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 !!! 
     } 
    } 

从ActivityArrivalFlights:

@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(); 
} 

这是整个概念,我想你英里ssed,我的代码是快速和肮脏的,所以清理它并根据需要使用。

注意! :在使用intent的活动之间传递对象(intent.putExtra(...)将传递一个对象的副本而不是同一个对象)。

+0

谢谢,但这不是我所期待的。我知道这个概念。 想法是,我将机场对象的参考传递给ActivityArrivalFlights活动。对同一个对象所做的任何更改应该在任何地方都可见,因为它是同一个对象,我只是通过它的引用。让我想到的是为什么这些变化在主要活动中不可见。 –

+0

@DraganApostolski intent.putExtra传递对象的副本,而不是对象本身,这意味着通过任何类型的intent.getExtra接收到的对象上的某些东西将改变对象的副本。您可以通过使airporst静态(仅用于测试)来检查对象是否为副本,并将putExtra中传递的对象与原始静态对象(在MainActivity中定义)进行比较,比较refs:airports == intentAirports。所以好的做法就是像上面提到的那样返回新航班。 – Mercury

+0

我真的没有阅读这个方法的文档,我真的认为intent.putExtra传递一个引用。谢谢,现在知道我会找到一个解决方案。 –